マニュアルページ sbufprot.3
名前
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&) // 非公開
コピーコンストラクタと代入演算子は非公開です。 stream-
buf の コ ピー を 防止するようには実装されていません。
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 ライブラリの使
用」