[前へ] [次へ] [目次]

## エラー処理

EB ライブラリの関数の呼び出しは、常に成功するとは限りません。 たとえば、`EB_Book` オブジェクトを書籍に結びつける関数 `eb_bind()` には、引数として書籍のトップディレクトリを渡しますが、 存在しないディレクトリを指定した場合、処理は失敗に終わります。

一般にこうした事象は、ユーザが誤ったパスを指定したときに起こりますが、 メモリ不足のように、ユーザのミスが原因ではない失敗も起こりえます。

本章では、関数の呼び出しが失敗した場合の処理について説明します。

### エラーコードとエラーメッセージ

EB ライブラリの関数の多くは、戻り値として `EB_Error_Code` 型の値を返します。 処理が成功したときに返す値は `EB_SUCCESS` ですが、失敗したときは エラーの原因に応じて様々な値を返します。 このため、EB ライブラリでは次のような `EB_SUCCESS` との比較処理 がよく行われます。

>     EB_Error_Code error_code;

>     error_code = eb_bind(&book, "/mnt/cdrom");
>     if (error_code != EB_SUCCESS) {
>         printf("eb_bind() failed\n");
>         return;
>     }

エラーコードの値は、関数 `eb_error_message()` によって エラーメッセージに変換することもできます。 こうすることで、エラーの原因をアプリケーションプログラムのユーザに もう少し分かりやすく伝えることができます。

>     error_code = eb_bind(&book, "/mnt/cdrom");
>     if (error_code != EB_SUCCESS) {
>         printf("eb_bind() failed, %s\n",
>             eb_error_message(error_code));
>         return;
>     }

`error_code` が `EB_ERR_TOO_LONG_FILENAME` に セットされていれば、次のようなエラーメッセージが出力されます。

>     too long filename

あるいは、次のように日本語のメッセージかも知れません。

>     ファイル名が長すぎます

メッセージの国際化機能 (NLS) を無効にして EB ライブラリをコンパイル した場合は、常に英語のメッセージが返ります。 有効にした場合は、ロケールの設定によってどちらの言語のメッセージが 返るかが決まります。

本書ではプログラムを簡潔にするために、エラー処理は最低限しか行って いません。 けれども一般のアプリケーションプログラムでは、関数の呼び出しが成功 したかどうかを常にチェックし、処理が失敗した際はエラーメッセージを出力 して、ユーザにエラーの原因を伝えるのが望ましいといえます。

### エラーに対する寛容さ

`EB_Book` オブジェクトは、状態に関するパラメタをいくつか持って います。 オブジェクトが CD-ROM 書籍に結び付いているかどうかも、こうしたパラメタ のうちの一つです。

引数に `EB_Book` オブジェクトへのポインタを取る関数には、 あらかじめオブジェクトの特定のパラメタがセットされていることを前提と しているものもあります。 たとえば、`eb_path()` は、オブジェクトが書籍に結び付いていること を前提としています。 では、もしも書籍に結び付いていないオブジェクトを `eb_path()` に 渡したらどうなるでしょうか。

>     EB_Book book;
>     EB_Error_Code error_code;
>     char path[EB_MAX_PATH_LENGTH + 1];

>     eb_initialize_library();
>     eb_initialize(&book);
>     error_code = eb_path(&book, path);    /* どうなる? */

この場合、`eb_path()` は `EB_ERR_UNBOUND_BOOK` を 返します。 EB ライブラリの関数は、必要なパラメタがセットされていないオブジェクトを 検知して拒絶します。

しかしながら、参照マニュアルで明示されている場合を除いて、EB ライブラリ の関数は、与えられたポインタが `NULL` かどうかまでは調べません。 次のようなことをすると、プログラムを異常終了させてしまいます。

>     eb_bind(NULL, "/mnt/cdrom");    /* 異常終了! */
>     eb_bind(&book, NULL);           /* これも異常終了! */

### データ型の詳細

この節で説明しているデータ型を使うには、次のようにヘッダファイルを 読み込んで下さい。

>     #include <eb/error.h>

#### `EB_Error_Code` 型

データ型 `EB_Error_Code` は、EB ライブラリのエラーコードを 表します。 この型は符合付き整数型の別名として定義されていますので、2 つのコードを 2 項演算子 `==` と `!=` で一致比較することができます。

EB ライブラリでは、全部で `EB_NUMBER_OF_ERRORS` 個の フックコードを定義しています。 エラーコードの一覧については、 次の節 (「エラーコードの一覧」 を参照のこと) を参照して下さい。

### エラーコードの一覧

この節で説明しているエラーコードを使うには、次のようにヘッダファイルを 読み込んで下さい。

>     #include <eb/error.h>

#### 定数 `EB_SUCCESS`

成功。 エラーは起きていない。

#### 定数 `EB_ERR_MEMORY_EXHAUSTED`

EB ライブラリが `malloc()` を呼び出したが、`NULL` が返ってきた。

#### 定数 `EB_ERR_TOO_LONG_FILE_NAME`

与えられた書籍のパス名が長すぎる。

#### 定数 `EB_ERR_BAD_FILE_NAME`

書籍のパス名が不正である。

#### 定数 `EB_ERR_BAD_DIR_NAME`

ディレクトリ名が不正である。 (EB ライブラリの内部処理用なので、 このエラーコードがアプリケーションプログラムに返ることはありません。)

#### 定数 `EB_ERR_TOO_LONG_WORD`

与えられた検索語は長すぎる。

#### 定数 `EB_ERR_BAD_WORD`

与えられた検索語に不正な文字が含まれている。

#### 定数 `EB_ERR_EMPTY_WORD`

与えられた検索語は空である。

#### 定数 `EB_ERR_FAIL_GETCWD`

`getcwd()` もしくは `getwd()` が失敗した。

#### 定数 `EB_ERR_FAIL_OPEN_CAT`

EB ライブラリが、書籍のカタログファイルを開くことに失敗した。

#### 定数 `EB_ERR_FAIL_OPEN_CATAPP`

EB ライブラリが、appendix のカタログファイルを開くことに失敗した。

#### 定数 `EB_ERR_FAIL_OPEN_TEXT`

EB ライブラリが、書籍の本文ファイルを開くことに失敗した。

#### 定数 `EB_ERR_FAIL_OPEN_FONT`

EB ライブラリが、書籍の外字ファイルを開くことに失敗した。

#### 定数 `EB_ERR_FAIL_OPEN_APP`

EB ライブラリが、appendix ファイルを開くことに失敗した。

#### 定数 `EB_ERR_FAIL_OPEN_BINARY`

EB ライブラリが、バイナリデータファイルを開くことに失敗した。

#### 定数 `EB_ERR_FAIL_READ_CAT`

EB ライブラリが、書籍のカタログファイルを読み込むことに失敗した。

#### 定数 `EB_ERR_FAIL_READ_CATAPP`

EB ライブラリが、appendix のカタログファイルを読み込むことに失敗した。

#### 定数 `EB_ERR_FAIL_READ_TEXT`

EB ライブラリが、書籍の本文ファイルを読むことに失敗した。

#### 定数 `EB_ERR_FAIL_READ_FONT`

EB ライブラリが、書籍の外字ファイルを読み込むことに失敗した。

#### 定数 `EB_ERR_FAIL_READ_APP`

EB ライブラリが、appendix のメインファイルを読み込むことに失敗した。

#### 定数 `EB_ERR_FAIL_READ_BINARY`

EB ライブラリが、書籍のバイナリデータファイルを読み込むことに失敗した。

#### 定数 `EB_ERR_FAIL_SEEK_CAT`

EB ライブラリが、書籍のカタログファイルのシークに失敗した。

#### 定数 `EB_ERR_FAIL_SEEK_CATAPP`

EB ライブラリが、appendix のカタログファイルのシークに失敗した。

#### 定数 `EB_ERR_FAIL_SEEK_TEXT`

EB ライブラリが、書籍の本文ファイルのシークに失敗した。

#### 定数 `EB_ERR_FAIL_SEEK_FONT`

EB ライブラリが、書籍の外字ファイルのシークに失敗した。

#### 定数 `EB_ERR_FAIL_SEEK_APP`

EB ライブラリが、appendix のメインファイルのシークに失敗した。

#### 定数 `EB_ERR_FAIL_SEEK_BINARY`

EB ライブラリが、書籍のバイナリデータファイルのシークに失敗した。

#### 定数 `EB_ERR_UNEXP_CAT`

EB ライブラリが、書籍のカタログファイル内で、期待とは異なるデータ列を 見つけた。

#### 定数 `EB_ERR_UNEXP_CATAPP`

EB ライブラリが、appendix のカタログファイル内で、想定外のデータ列を 見つけた。

#### 定数 `EB_ERR_UNEXP_TEXT`

EB ライブラリが、書籍の本文ファイル内で、想定外のデータ列を見つけた。

#### 定数 `EB_ERR_UNEXP_FONT`

EB ライブラリが、書籍の外字ファイル内で、想定外のデータ列を見つけた。

#### 定数 `EB_ERR_UNEXP_APP`

EB ライブラリが、appendix のメインファイル内で、想定外のデータ列を 見つけた。

#### 定数 `EB_ERR_UNEXP_BINARY`

EB ライブラリが、書籍のバイナリデータファイル内で、想定外のデータ列を 見つけた。

#### 定数 `EB_ERR_UNBOUND_BOOK`

呼び出された EB ライブラリの関数は、書籍に結び付けられた `EB_Book` オブジェクトを引数にとるが、与えられたオブジェクトは 書籍に結び付けられていなかった。

#### 定数 `EB_ERR_UNBOUND_APP`

呼び出された EB ライブラリの関数は、appendix に結び付けられた `EB_Appendix` オブジェクトを引数にとるが、与えられた オブジェクトは appendix に結び付けられて いなかった。

#### 定数 `EB_ERR_NO_SUB`

書籍は副本を一つも持っていない。

#### 定数 `EB_ERR_NO_APPSUB`

appendix は副本を一つも持っていない。

#### 定数 `EB_ERR_NO_FONT`

選択中の副本は、外字を一種類も持っていない。

#### 定数 `EB_ERR_NO_TEXT`

選択中の副本は、本文データを持っていない。

#### 定数 `EB_ERR_NO_CUR_SUB`

呼び出された関数は、副本が選択されている `EB_Book` オブジェクトを引数としてとるが、与えられたオブジェクトでは選択されて いなかった。

#### 定数 `EB_ERR_NO_CUR_APPSUB`

呼び出された関数は、副本が選択されている `EB_Appendix` オブジェクトを引数にとるが、与えられたオブジェクトでは選択されて いなかった。

#### 定数 `EB_ERR_NO_CUR_FONT`

呼び出された関数は、外字が選択されている `EB_Book` オブジェクトを引数にとるが、与えられたオブジェクトでは選択されて いなかった。

#### 定数 `EB_ERR_NO_CUR_BINARY`

呼び出された関数は、バイナリデータの読み込み要求をセットしている `EB_Book` オブジェクトを引数にとるが、与えられたオブジェクトでは セットされていなかった。

#### 定数 `EB_ERR_NO_SUCH_SUB`

`EB_Book` オブジェクトと副本コードが関数に与えられたが、 `EB_Book` オブジェクトに結び付けられている書籍は、その 副本コードに一致する副本を持っていない。

#### 定数 `EB_ERR_NO_SUCH_APPSUB`

`EB_Appendix` オブジェクトと副本コードが関数に与えられたが、 `EB_Appendix` オブジェクトに結び付けられている appendix は、 その副本コードに一致する副本を持っていない。

#### 定数 `EB_ERR_NO_SUCH_FONT`

`EB_Book` オブジェクトと外字の縦のサイズが関数に与えられたが、 `EB_Book` オブジェクトに結びつけられていた書籍で選択中の副本は、 そのサイズの外字を持っていない。

#### 定数 `EB_ERR_NO_SUCH_CHAR_BMP`

`EB_Book` オブジェクトと文字番号が関数に与えられたが、 `EB_Book` オブジェクトに結び付けられていた書籍で選択中の副本は、 その番号の外字のビットマップデータを持っていない。

#### 定数 `EB_ERR_NO_SUCH_CHAR_TEXT`

`EB_Appendix` オブジェクトと文字番号が関数に与えられたが、 `EB_Appendix` オブジェクトに結び付けられている appendix で 選択中の副本は、その番号の外字の代替文字列を持っていない。

#### 定数 `EB_ERR_NO_SUCH_SEARCH`

選択中の副本は、指定された検索メソッドを持っていないので、検索は行えない。

#### 定数 `EB_ERR_NO_SUCH_HOOK`

不正なフックコードが関数に渡された。

#### 定数 `EB_ERR_NO_SUCH_BINARY`

指定された位置に、指定された形式のバイナリデータは存在しない。

#### 定数 `EB_ERR_DIFF_CONTENT`

アプリケーションプログラムからテキストデータの取得を要求されたが、指定 されたテキストデータの種類が、前回リクエストされたときと一致していない。

#### 定数 `EB_ERR_NO_PREV_SEARCH`

`eb_hit_list()` が呼び出されたが、アプリケーションプログラム から前もって検索のリクエストがなされていない。

#### 定数 `EB_ERR_NO_SUCH_MULTI_ID`

`EB_Book` オブジェクトと複合検索コードが関数に渡されたが、 結び付けられた書籍で選択中の副本は、そのコードに一致する複合検索を持って いない。

#### 定数 `EB_ERR_NO_SUCH_ENTRY_ID`

`EB_Book` オブジェクトと複合検索エントリコードが関数に 渡されたが、結び付けられた書籍で選択中の副本は、そのエントリコードに 一致する複合検索エントリを持っていない。

#### 定数 `EB_ERR_TOO_MANY_WORDS`

アプリケーションプログラムから条件検索もしくは複合検索の検索をリクエスト されたが、検索語の個数が多すぎる。

#### 定数 `EB_ERR_NO_WORD`

アプリケーションプログラムから条件検索もしくは複合検索の検索をリクエスト されたが、検索語がすべて空である。

#### 定数 `EB_ERR_NO_CANDIDATES`

`eb_multi_entry_candidates()` が呼び出されたが、 指定された複合検索エントリは、検索語の候補一覧データを持っていない。

#### 定数 `EB_ERR_END_OF_CONTENT`

`eb_forward_text()` あるいは `eb_backward_text()` で本文の頭出しを行おうとしたが、すでに本文の末尾ないし先頭に達していて、 それ以上先に進むことができなかった。

#### 定数 `EB_ERR_NO_PREV_SEEK`

あらかじめ `eb_seek_text()` でシークを行っていない状態で、 テキストデータの読み込みや頭出しを行おうとした。

#### 定数 `EB_ERR_EBNET_UNSUPPORTED`

この EB ライブラリは、遠隔ホストへのアクセスには対応していない。

#### 定数 `EB_ERR_EBNET_FAIL_CONNECT`

遠隔ホストへのアクセスを試みたが、サーバ (EBNETD) に接続できなかった。

#### 定数 `EB_ERR_EBNET_SERVER_BUSY`

遠隔ホストへの接続を行ったが、書籍にアクセスしているクライアントの数が すでに上限に達しているため、その書籍を利用できなかった。

#### 定数 `EB_ERR_EBNET_NO_PERMISSION`

遠隔ホストへの接続を行ったが、その書籍への利用権限がないため、サーバ からアクセスを拒否された。

#### 定数 `EB_ERR_UNBOUND_BOOKLIST`

呼び出された EB ライブラリの関数は、遠隔ホストに結び付けられた `EB_BookList` オブジェクトを引数にとるが、与えられたオブジェクト は遠隔ホストに結び付けられていなかった。

#### 定数 `EB_ERR_NO_SUCH_BOOK`

`EB_BookList` オブジェクトと書籍の要素番号を関数に渡されたが、 `EB_BookList` に結び付けられた遠隔ホスト上には、その要素番号に 該当する書籍は存在しない。

### 関数の詳細

この節で説明している関数を使うには、次のようにヘッダファイルを読み込んで 下さい。

>     #include <eb/error.h>

#### `const char *eb_error_string (EB_Error_Code error_code)`

関数 `eb_error_string()` は、エラーコード error_code を文字列に変換したものを返します。 文字列の文字コードは、ASCII になります。 たとえば、エラーコード値 `EB_SUCCESS` を渡すと文字列 `"EB_SUCCESS"` を返します。 未知のエラーコードを渡したときは、`"EB_ERR_UNKNOWN"` を返します。

#### `const char *eb_error_message (EB_Error_Code error_code)`

関数 `eb_error_message()` は、エラーコード error_code に対応したメッセージを文字列にして返します。 関数の返すメッセージは、英語か日本語になります。

国際化機能を有効にして EB ライブラリをコンパイルしていない場合は、常に 英語のメッセージを返します。 このときのメッセージの文字コードは、ASCII になります。

メッセージの国際化機能 (NLS) を有効にして EB ライブラリをコンパイル した場合は、ロケールの設定に応じてどちらの言語のメッセージを返すのか が決まります。 また、GNU gettext バージョン 0.36 以降では iconv() と連携することにより、 メッセージの文字コードもロケールに応じて変化します。 gettext が iconv() との連携を行わなければ、英語のメッセージは ASCII、 日本語のメッセージは日本語 EUC になります。 この関数の呼び出しによって、gettext のテキストドメインの設定は変化 しません。

未知のエラーコードを渡したときに返すメッセージは、英語では `"unknown error"`、日本語では `"未知のエラーです"` になります。

[前へ] [次へ] [目次]