SBUFPROT(3CC4)

名前
sbufprot - ストリームバッファ基底クラスの限定公開インタフェース

形式

#include <iostream.h>

typedef long streampos;
typedef long streamoff;

class ios  : virtual public unsafe_ios, public stream_MT {
public:
        enum open_mode  {
            in       = 0x01,    // 読み取り用にオープン
            out      = 0x02,    // 書き込み用にオープン
            ate      = 0x04,    // EOF までシークする
            app      = 0x08,    // 追加モード: EOF 以降に追加
            trunc    = 0x10,    // ファイルがあれば内容をクリア
            nocreate = 0x20,    // ファイルがなければオープンを失敗させる
            noreplace= 0x40     // ファイルがあればオープンを失敗させる
        };
        // ストリームのシーク方向
        enum seek_dir { beg=0, cur=1, end=2 };

        // 残りの部分については ios(3CC4) を参照 ...

} ;

class streambuf : public stream_MT {
public:
        streambuf() ;
        streambuf(char* p, int len);
        void    dbp() ;
protected:
        int     allocate();
        char*   base();
        int     blen();
        char*   eback();
        char*   ebuf();
        char*   egptr();
        char*   epptr();
        void    gbump(int n);
        char*   gptr();
        char*   pbase();
        void    pbump(int n);
        char*   pptr();
        void    setg(char* eb, char* g, char* eg);
        void    setp(char* p, char* ep);
        void    setb(char* b, char* eb, int a=0);
        int     unbuffered();
        void    unbuffered(int);
        virtual int     doallocate();
        virtual ~streambuf() ;
        int     allocate_unlocked();
        char*   base_unlocked();
        int     blen_unlocked();
        char*   eback_unlocked();
        char*   ebuf_unlocked();
        char*   egptr_unlocked();
        char*   epptr_unlocked();
        void    gbump_unlocked(int n);
        char*   gptr_unlocked();
        char*   pbase_unlocked();
        void    pbump_unlocked(int n);
        char*   pptr_unlocked();
        void    setg_unlocked(char* eb, char* g, char* eg);
        void    setp_unlocked(char* p, char* ep);
        int     unbuffered_unlocked();
        void    unbuffered_unlocked(int);
streambuf(char* buf, int len);

public:
        virtual int     pbackfail(int c);
        virtual int     overflow(int c=EOF);
        virtual int     underflow();
        virtual streambuf*
                setbuf(char* p, int len);
        streambuf*
                setbuf(unsigned char* p, in len);
        virtual streampos
                seekpos(streampos, int =ios::in|ios:out);
        virtual streampos
                seekoff(streamoff, seek_dir, int =ios::in|ios:out);
        virtual int     sync();
};

機能説明

streambuf の公開インタフェースについては、 sbuf.pub(3CC4) を参照してください。 ここでは、使用可能なバッファクラスを派生させるときに必要な 限定公開インタフェースについて説明します。 クラス streambuf は、基底クラスとしてだけ使用するように 設計されています。したがって、クラス streambuf のオブジェクトは作成できません。 代わりに、3 つの派生バッファクラスが定義されています。 filebuf(3CC4) 、 ssbuf(3CC4) 、 stdiobuf(3CC4) を参照してください。

一般に、ここで説明する非仮想関数は、 変更して使用するようには設計されていません。 これらの関数は、低レベルのバッファ管理機能を提供します。

ここでは、各仮想関数の機能と、そのデフォルトの動作について説明します。 関数のデフォルトの動作が作成する派生バッファクラスに適していれば、 その関数を変更する必要はありません。 たとえば、入力ソースを持たないバッファクラスは、アンダーフロー時には EOF を返すこと (デフォルトの動作) 以外、何も行いません。 デフォルトの動作が適さない場合は、 その関数を変更し、クラス固有のバージョンを用意しなければなりません。 たとえば、ファイルに接続されている入力バッファは、 アンダーフロー時にもさらにデータの読み込みを試みなければなりません。 クラス固有の仮想関数は、 その動作に依存する他の関数を続けて機能させるために、 streambuf 版の仕様に従わなければなりません。

streambuf の限定公開メンバーー関数は、それぞれロック機能を使用して streambuf をマルチスレッド環境で正しく動作させます。

streambuf を MT-safe にするロック機能を持たない関数も提供されています。 これらの関数は、名前の接尾辞 "_unlocked" で区別されます。

  コンストラクタと

  代入演算子

streambuf()
    コンストラクタ。空の入力ストリームのための空のバッファを作成します。

streambuf(ptr, len)
    コンストラクタ。 空のバッファか、または ptr が指す場所から始まる len バイトの reserve 領域 (下記参照) を作成します。

streambuf(streambuf&) // 非公開
    operator= (streambuf&) // 非公開
    コピーコンストラクタと代入演算子は非公開です。 streambuf のコピーを防止するようには実装されていません。 streambuf をコピーする代わりに、1 つの streambuf を指す複数のポインタの受け渡しを 行うことがあります。

  入力領域、出力領域

  確保領域
streambuf のバッファは、入力領域、出力領域、確保領域 (バッファ領域と同じ) の 3 つの部分から 構成されていると見なすことができます。 入力領域には、入力データとしてそのまま使用できる文字が含まれます。 出力領域には、 最終的な宛先によってまだ消費されていない (フラッシュされていない) 出力文字 が保持されます。 入力領域や出力領域は、別々にも、また重複させても確保することができます。 確保領域はバッファ全体に対応し、 入力領域と 出力領域もその中に含まれます。 入力領域と 出力領域は、確保領域の残りの部分まで拡大できます。 入出力操作中、入力領域と 出力領域のサイズは、 常に合計バッファサイズ (確保領域のサイズ) の範囲内で 拡張したり縮小したりします。

バッファとその領域は、非公開のポインタ変数によって定義されます。 それは、限定公開のメンバー関数によって読み込みや設定が可能です。 後述するポインタは、文字間を指していると考えてください。 すなわち、ポインタは 1 つの文字を指していますが、 文字の直前を指しているものとして調べる方が便利です。 これにより、 sbuf.pub(3CC4) で説明されている抽象的な表現に対応するものが確立されます。

  ポインタを調べるための非仮想関数

char* ptr = sbuf.base()
    確保領域の先頭を指すポインタを返します。

char* ptr = sbuf.ebuf()
    確保領域のすぐ後ろを指すポインタを返します。 base() から ebuf()-1 までの領域が確保領域です。 ebuf()==base() である場合、ストリームはバッファリングされません。

char* ptr = sbuf.gptr()
    入力領域の先頭を指すポインタ、すなわち、 次にフェッチする文字があればその文字を指すポインタを返します。 直ちに使用できる文字は、 gptr()から egptr()-1 までの領域にあります。 egptr()<=gptr() である場合、使用できる文字は存在しません。

char* ptr = sbuf.egptr()
    入力領域のすぐ後ろを指すポインタを返します。 このポインタは、 gptr() で可能な最大値を示します。

char* ptr = sbuf.eback()
    gptr() で可能な最小値を返します。文字をプットバック ( get ポインタをバックアップする) のために eback() から gptr()-1 までの領域を使用できます。 back()==gptr() のとき、プットバック操作を試みても失敗することがあります。

char* ptr = sbuf.pptr()
    出力領域の先頭を指すポインタを返します。 このポインタは、次に格納できる文字があれば、その文字の位置を示します。

char* ptr = sbuf.pbase()
    出力領域に使用できる領域の先頭を指すポインタを返します。 このポインタは、 pptr() で可能な最小値を示します。 pbase() から pptr()-1までの領域は バッファに格納されているが、まだ使用されていない文字を表します。

char* ptr = sbuf.epptr()
    出力領域のすぐ後ろを指すポインタを返します。 このポインタは、 pptr() で可能な最大値を示します。 pptr() から epptr() までの領域は、 文字を格納するための領域として、フラッシュ操作なしですぐに使用できます。

  ポインタ設定のための

  非仮想関数

ポインタを設定するためには、 ここで取り上げる関数を使用する必要があります。 各種ポインタ間の整合性を保証するため、 ポインタに直接アクセスすることはできません。 関数のポインタ引数は、何も領域 (入力、出力、確保) がないことを示す場合はすべて ゼロでなければなりません。 値が等しい (ゼロを除く) ポインタを複数使用すると、 不適切な動作が行われることがあります。

sbuf.setb(buf, end, del)
    確保領域 (バッファ) を確立します。 base() を buf に設定し、 ebuf() を end に設定します。 del がゼロ以外の場合、 base() が setb() の別の呼び出しによって変更されるたび、 または streambuf のデストラクタが呼び出されるときに、 バッファが削除 ( delete ) されます。 del がゼロの場合、 これらの関数によってバッファが自動的に削除されることはありません。

sbuf.setg(back, g, eg)
    入力領域を確立します。 eback() を back に、 gptr() を g に、 egptr() を eg にそれぞれ設定します。

sbuf.setp(p, ep)
    出力領域を確立します。 pptr() を p に設定し、 epptr() を ep に設定します。

  その他の非仮想関数

int i = sbuf.allocate()
    この関数は、 streambuf のどの非仮想メンバーによっても呼び出されることはありません。 指定されていないデフォルトのサイズの 確保領域のセットアップを試みます。 確保領域がすでに存在する場合、または streambuf がバッファリングしないように設定されている場合、 ゼロを返して何も行いません。それ以外の場合、 仮想関数 doallocate() を呼び出すことによって領域の割り当てを試みます。 割り当てに成功した場合は 1、失敗した場合は EOF を返します。 unbuffered() と doallocate() については、下記を参照してください。

int i = sbuf.blen()
    確保領域 ebuf()-base() のサイズを文字数で返します。

sbuf.gbump(n)
    符号つきの量 n を妥当性検査なしで get ポインタに追加します。

sbuf.pbump(n)
    符号つきの量 n を妥当性検査なしで get ポインタに追加します。

int i = sbuf.unbuffered()
    sbuf.unbuffered(i)
    streambuf は、確保領域が割り当てられているかどうかに関係なく、 ストリームがバッファリングされているかどうかを追跡するための非公開関数を 持っています。主にこの関数は、 allocate() によって 確保領域を実際に割り当てるかどうかを 制御するために使用します。 上の引数なしの形式では、変数がセットされていればゼロ以外の値、 セットされていなければゼロを返します。 下の形式では、引数 i がゼロでない場合に変数をセットし、 ゼロの場合には変数をクリアします。

dpb()
    streambuf のすべての状態変数をテキストとして、 ファイル記述子 1 (標準出力) に直接書き込みます。 このデータは、実装のデバッグに利用できます。 この関数は公開関数です。 したがって、それが論理的に限定公開関数の一部であっても、 デバッグの目的でどこからでも呼び出すことができます。

  仮想関数

ここで取り上げる関数は、 上記で示した特別なバッファクラスによって再定義できる、 または再定義しなければならない仮想関数です。 再定義した関数は、それらに依存する他の関数が適切に動作するように、 ここで示す仕様に従っていなければなりません。 ここではまた、各関数の基底クラス版のデフォルト動作に ついても示します。

int i = sbuf.doallocate()
    この関数は、 unbuffered() と base() がともにゼロの場合に allocate によって呼び出されます。 適切なサイズのバッファを作成するように試みます。 バッファの作成に成功した場合は、 setb を呼び出して 確保領域を確立し、 ゼロよりも大きい値を返されなければなりません。 バッファの作成に失敗した場合は EOF を返します。デフォルトでは、 new を使用してバッファを割り当てます。

int i = sbuf.overflow(c)
    この関数は、 通常 出力領域がフル状態になっているときに 別の文字が格納されようとした場合に呼び出され、 領域内の文字を消費 (出力にフラッシュ) します。 c が EOF 以外のとき、 overflow は、出力領域にすでに存在する文字の後ろにある文字を格納するか、 消費しなければなりません。 エラーが発生した場合は EOF 、正常終了した場合はそれ以外の任意の値を返します。

    基底クラス版のデフォルトの動作は未定義であるため、 各派生クラスでは独自の overflow を定義する必要があります。 通常、派生クラス版関数は 出力領域内の文字 ( pbase() と pptr() の間にあるもの) を消費し、 setp() を呼び出して新しい 出力領域をセットアップした後、 cが EOF でなければ、( sputc() を用いて) それを格納します。

int i = sbuf.pbackfail(c)
    この関数は、文字列 c のプットバックが試みられたときにプットバック領域に 領域が残っていなかった場合 ( eback()==gptr() のとき) に呼び出されます。 外部デバイスの再配置などによってこの状況を処理できれば、 派生クラス版の pbackfail はその処理を行なって c を返します。 何らかの理由によって文字を書き戻すことができない場合は、 EOF を返さなければなりません。 基底クラス版のデフォルトでは、 EOFを返します。

streampos pos = sbuf.seekoff(off, dir, mode)
    この関数のパラメタ、戻り値、目的については、 sbuf.pub(3CC4) を参照してください。特に gptr() や pptr() とは対照的に、 get と put の抽象ポインタは可能であればこの関数によって変更されます。 派生クラス版は、ストリームが再配置をサポートしていないか、 何らかのエラーがあった場合は EOF を、それ以外の場合は新しい位置を返さなければなりません。 基底クラス版のデフォルトでは、 EOF を返します。

streampos pos2 = sbuf.seekpos(pos, mode)
    この関数のパラメタ、戻り値、目的については、 sbuf.pub(3CC4) を参照してください。特に gptr() や pptr() とは対照的に、 get と put の抽象ポインタは可能であればこの関数によって変更されます。 基底クラス版のデフォルトでは次の値を返します。
    sbuf.seekoff( (streamoff)pos, ios::beg, mode )
    すなわち、通常は派生クラスで seekoff を実装し、基底クラス seekpos を継承するだけでよいということになります。

streambuf* sb = sbuf.setbuf(ptr, len)
    ptr が指す位置から始まる len バイトの配列をバッファ領域として 使用するように要求します。 ptr がゼロの場合、または len がゼロ以下の場合は、 バッファなし ( unbuffered ) 状態を要求します。 派生クラス版では、要求を無視するように選択できます。 要求を受け付ける場合は sbuf のアドレス、それ以外の場合は EOF を返さなければなりません。 基底クラス版のデフォルトでは、 確保領域がない場合に要求を受け付けます。

int i = sbuf.sync()
    streambuf をその実際の文字ストリームと同期させます。 派生クラス版では、 出力領域内のすべての文字をその最終的な宛先にフラッシュし、 可能であれば入力バッファ内のすべての文字をその入力元に戻さなければなりません。 さらに、エラー時には EOF 、正常終了時にはゼロを返さなければなりません。 基底クラス版のデフォルトでは、保留中の入力文字または出力文字がない 場合 ( in_avail() と out_waiting() がともにゼロの場合) にゼロ、 それ以外の場合は EOF を返します。

int i = sbuf.underflow()
    この関数は 入力領域が空の場合に呼び出され、 入力用の文字を (あるソースから) 供給します。ただし、 それ以外の場合に呼び出すこともできます。 入力領域が空でない場合は、先頭の文字だけを返し (get ポインタは 進めません)、それ以外のことは行わないでください。 入力領域が空の場合は、入力領域を新しく作成し、 新しい入力データがあればそれを取得し、 その先頭の文字を返さなければなりません。 基底クラス版のデフォルトの動作は未定義です。 したがって、各派生クラスで独自の underflow を定義しなければなりません。

関連項目

ios.intro(3CC4)、 filebuf(3CC4)、 ios(3CC4)、 sbufpub(3CC4)、 ssbuf(3CC4)、 stdiobuf(3CC4) 『C++ ライブラリ・リファレンス』の第 3 章「iostream ライブラリ」 および第 4 章「マルチスレッド環境での従来型の iostream ライブラリの使用」