nlib
nn::nlib::InputStream クラスabstract

入力ストリームの基底クラスです。このクラスを実体化することはできません。 [詳解]

#include "nn/nlib/InputStream.h"

+ nn::nlib::InputStream の継承関係図

公開メンバ関数

errno_t GetErrorValue () const noexcept
 エラー値を取得します。 [詳解]
 
size_t Pos () const noexcept
 ストリーム上の現在位置を返します。 [詳解]
 
uint64_t Pos64 () const noexcept
 ストリーム上の現在位置を64bit値で返します。 [詳解]
 
bool IsEos () noexcept
 ストリームを最後まで読み終えている場合trueを返します。最後まで読み終えていない場合やエラーが発生している場合はfalseを返します。 [詳解]
 
int Read () noexcept
 ストリームから1バイトを読み込みます。 [詳解]
 
NLIB_CHECK_RESULT int Peek () noexcept
 ストリームを消費せずに次の1バイトを読み込みます。 [詳解]
 
size_t Skip (size_t nbytes) noexcept
 nBytes を読み飛ばします。 [詳解]
 
size_t Read (void *ptr, size_t nbytes) noexcept
 ptr で示されるメモリにnBytes 読み込みます。 [詳解]
 
bool Close () noexcept
 ストリームを閉じます。成功した場合にはtrueを返します。 [詳解]
 
 operator bool () const
 内部でエラーが発生していなければtrueを返します。
 
基本的なメンバ関数
constexpr InputStream () noexcept
 コンストラクタです。派生クラスから呼び出されます。
 
virtual ~InputStream () noexcept
 デストラクタです。派生クラスから呼び出されます。
 

限定公開メンバ関数

派生クラスから利用する関数
void ResetBuffer (void *p, size_t nbytes) noexcept
 InputStreamが持つバッファを設定します。 [詳解]
 
void SetError (errno_t e) const noexcept
 InputStreamにエラーを設定します。 [詳解]
 

詳解

入力ストリームの基底クラスです。このクラスを実体化することはできません。

説明
同期かつシーケンシャルなアクセスI/Fを持つ入力ストリームの基底となります。 実際のデータの読み込み先は、派生クラスによって定義されます。
1バイトずつデータを読む処理は以下のようにコーディングすることができます。
InputStream& is = .... 派生クラスのオブジェクト ....;
int c;
while ((c = is.Read()) >= 0) {
// cに読み込んだバイトを利用した処理
}
if (nlib_is_error(is)) {
// 読込中にエラーが発生
}
バッファを用意していて、特定のバイト数をまとめて読み込みたい場合は、以下のようにコーディングすることができます。
InputStream& is = .... 派生クラスのオブジェクト ....;
uint8_t* buf = ... N bytesのメモリ ...;
size n = is.Read(buf, N);
if (n == 0 && nlib_is_error(is)) {
// 読込中にエラーが発生
}
テキストデータ(UTF-8)を読み込みたい場合は、TextReaderオブジェクトを利用します。 改行を正規化し、UTF-8をチェックしてUTF-32に変換してからユーザーに渡します。
InputStream& is = .... 派生クラスのオブジェクト ....;
TextReader r;
if (nlib_is_error(r.Init(&is))) { エラー; }
int c;
while ((c = is.Read()) >= 0) {
// cに読み込んだコードポイント(UTF-32)を利用した処理
}
if (nlib_is_error(r)) {
// 読込中にエラーが発生
}

派生クラスの実装のための情報

InputStreamクラスの仕様は予告なしに変更される可能性があるので、出来るだけ派生クラスを独自に実装しない方がリスクは低いですが、必要な場合、派生クラスは以下の仮想関数をオーバーライドすることで定義できます。
size_t FillBuffer_(void* p, size_t nbytes)
引数p は設定されるデータへのポインタで、nBytes はサイズです。 ユーザーがデータを読み込もうとして、InputStream内のバッファにデータがなかった場合に呼ばれます。 p には内部バッファ、又はユーザーが指定したバッファのポインタが入ります。
戻り値は実際に設定されたデータのサイズでnBytes 以下の値です。 エラーかデータの末尾の場合、かつその場合のみに0を返すことができます。 データがまだ届いていない、というような場合は内部でブロックする必要があります。
また、後述のGetWorkBuffer_()でバッファが設定されなかった場合は、pNULLが入ってコールされることがあります。 その場合はResetBuffer()をコールしてInputStreamの内部バッファをセットする必要があります。
エラーケースの対応として以下を例として挙げます。
  • 対応デバイスがない場合(ハンドルが無効等)は、EBADFを設定し0を返します。
  • 途中で読み込み失敗が確定した場合はエラー(ex. EIO)を設定し0を返します。
エラー場合、データを途中まで読めた場合も0を返さなくてはならないことに注意してください。
bool Close_()
内部のハンドル等をクローズします。 どのような場合でも内部で保持する関連リソース全てを解放する実装になっている必要があります。 また、基底クラスのデストラクタからはClose_()が呼ばれないことに注意してください。
エラーケースの対応として以下を例として挙げます。
  • 対応デバイスがない場合(ハンドルが無効等)は、EBADFを設定しfalseを返します。
  • クローズの際の動作等で失敗した場合、何らかのエラー(ex. EIO)を設定しfalseを返します。
エラーの場合でも、ハンドル等の内部リソースの解放を確実に行うことが必要であることに注意してください。
void* GetWorkBuffer_(size_t* nbytes)
is_buf_NULLの場合、InputStreamはまずこの関数を呼び出してバッファを獲得しようとします。 戻り値がバッファへのポインタで、nBytes にサイズが設定されます。 バッファ自体の所有権は派生クラス側にあるので、バッファの解放は派生クラスのコードで行う必要があります。
メモリの確保等に失敗してバッファを渡せない場合は、NULLを返しnBytes に0を設定する必要があります。
この関数をオーバーライドしない場合はNULLを返し、nBytes には-1が代入されます。 この場合、InputStreamFillBuffer_()においてバッファを獲得しようとします。

InputStreamの設計に関するメモ

InputStreamでデータを読むと必ずデータがバッファがキャッシュされます。 このキャッシュはデバイスからの読み込みをまとめて行うことが目的なのではなく、仮想関数の呼び出しを抑制するためのものです。
InputStreamの設計にあたり、以下のようなインターフェイスクラスを基底に置く設計はシンプルなものになります。
class InputStream {
public:
virtual int Read()=0;
virtual int Peek()=0;
...
};
しかしながら、1バイトずつデータを呼び出した場合の仮想関数のオーバーヘッドが大きく、現実的な利用には適しません。

InputStream.h16 行目に定義があります。

関数詳解

§ Close()

nn::nlib::InputStream::Close ( )
noexcept

ストリームを閉じます。成功した場合にはtrueを返します。

戻り値
成功した場合はtrue
説明
falseの場合は、途中で何らかの処理が失敗しています。もし失敗した場合も再度クローズする必要はありません。

§ GetErrorValue()

nn::nlib::InputStream::GetErrorValue ( ) const
inlinenoexcept

エラー値を取得します。

戻り値
エラー値
説明
0以外の場合はエラーです。エラー値は一般には実装依存になります。

InputStream.h31 行目に定義があります。

§ IsEos()

nn::nlib::InputStream::IsEos ( )
inlinenoexcept

ストリームを最後まで読み終えている場合trueを返します。最後まで読み終えていない場合やエラーが発生している場合はfalseを返します。

戻り値
trueの場合ストリームの最後に到達しています。

InputStream.h35 行目に定義があります。

§ Peek()

nn::nlib::InputStream::Peek ( )
inlinenoexcept

ストリームを消費せずに次の1バイトを読み込みます。

戻り値
読み込んだデータ、又は-1
説明
読み込んだデータを返します。 失敗した場合やストリームの最後まで読み終えた場合は-1を返します。

InputStream.h51 行目に定義があります。

§ Pos()

nn::nlib::InputStream::Pos ( ) const
inlinenoexcept

ストリーム上の現在位置を返します。

戻り値
ストリーム上の現在位置(読み込んだバイト数)
説明
ストリームを閉じた後にこのメソッドを利用しても正しい値は得られない点に注意してください。

InputStream.h33 行目に定義があります。

§ Pos64()

nn::nlib::InputStream::Pos64 ( ) const
inlinenoexcept

ストリーム上の現在位置を64bit値で返します。

戻り値
ストリーム上の現在位置(読み込んだバイト数)

InputStream.h34 行目に定義があります。

§ Read() [1/2]

nn::nlib::InputStream::Read ( )
inlinenoexcept

ストリームから1バイトを読み込みます。

戻り値
読み込んだデータ、又は-1
説明
読み込んだデータを返します。 失敗した場合やストリームの最後まで読み終えた場合は-1を返します。
従って-1を読み込んだ場合にはエラーであるかストリームの末端であるかを判定する必要があります。
InputStream& is = ....;
c = is.Read();
if (c < 0) {
if (nlib_is_error(is)) {
// エラーが発生している
} else {
// ストリームの終端に到達している
}
}

InputStream.h43 行目に定義があります。

§ Read() [2/2]

nn::nlib::InputStream::Read ( void *  ptr,
size_t  nbytes 
)
inlinenoexcept

ptr で示されるメモリにnBytes 読み込みます。

引数
[in,out]ptr読み込んだデータを格納するメモリ
[in]nbytes読み込むバイト数
戻り値
実際に読み込んだバイト数
説明
読み込んだバイト数が0の場合はストリームの終わりかエラーです。 それ以外の場合は、nBytes より小さい値が戻ってきた場合でもストリームの終わりではないかもしれません。

InputStream.h60 行目に定義があります。

§ ResetBuffer()

nn::nlib::InputStream::ResetBuffer ( void *  p,
size_t  nbytes 
)
inlineprotectednoexcept

InputStreamが持つバッファを設定します。

引数
[in]pバッファへのポインタ
[in]nbytesバッファ・サイズ

InputStream.h82 行目に定義があります。

§ SetError()

nn::nlib::InputStream::SetError ( errno_t  e) const
inlineprotectednoexcept

InputStreamにエラーを設定します。

引数
[in]eエラー値
説明
既に0以外のエラーが設定されている場合は、エラー値は上書きされません。

InputStream.h86 行目に定義があります。

§ Skip()

nn::nlib::InputStream::Skip ( size_t  nbytes)
noexcept

nBytes を読み飛ばします。

引数
[in]nbytes読み飛ばすバイト数
戻り値
実際に読み飛ばしたバイト数
説明
データを読み飛ばす場合、Read()でデータを読み捨てるより効率がよい場合があります。

このクラス詳解は次のファイルから抽出されました: