試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

Vala言語におけるユーザ定義例外について

Pythonの例外とその処理に関する覚え書き(ユーザ定義の例外など)Pythonによるユーザ定義例外の例を作成したが、これと同じことをVala言語で書いてみた。

メモ

例外の定義

下のような形式でエラードメインというものを定義する。

errordomain FooBarError  // 大まかな種類
{
  FOO_FAILED,  // 種類ごとのエラーコード
  INVALID_HOGE,
  BAR_NOT_FOUND,
}

ドメイン文字列では大まかなエラーの種類を定義し、その中で、より詳しい内容に合わせた名前で個別のエラーコードを定義することになる。

例外を出す
  • 例外を出すかもしれない関数の定義部分では、渡される引数の閉じ丸括弧の右に「throws [エラードメイン名]」を記述
  • 例外を実際に出す部分では「throw new [エラードメイン名].[エラーコード]([メッセージ]);」を記述
  • 既存(定義済み)の「throws」付き関数(例外を出すかもしれない関数)を別の関数から呼んだときにその例外を呼び出し側でとらえられるようにしたい場合にも、その関数の定義部分には「throws [エラードメイン名]」が必要
  • 例外を出す部分の引数として渡したメッセージはcatch節でとらえたエラーオブジェクトのメンバmessageとして取り出すことができる
public void func () throws FooBarError
{
  ...
  if ( ... )
    throw new FooBarError.INVALID_FOGE ("message");
  ...
}

public void func2 () throws FooBarError
{
  ...
  func1 ();
  ...
}

...

try
{
  func2 ();
}
catch (FooBarError e)
{
  print ("FooBarError: %s\n", e.message);
}

コード

テストのためにわざとtry節を使用していない部分があるため、コンパイル時に警告が出る。
[任意]ファイル名: userexceptiontest.vala

using GLib;

/*
 * valac -o userexceptiontest userexceptiontest.vala
 */

namespace UserExceptionTest
{
  /* 正規表現パターンが見つからないときの例外 */
  errordomain FindError  // 大まかな種類
  {
    PATTERN_NOT_FOUND,  // 種類ごとのエラーコード
    ERRCODE2,           // 複数個定義可能(今回は使用しない)
    ERRCODE3,
  }
  /* 正規表現パターンのチェックを行うツール */
  class PatternChecker
  {
    GLib.Regex regexobj;
    string ptn;
    /* 「throws GLib.RegexError」を書かないとmain()側でつかめない */
    public PatternChecker (string ptn) throws GLib.RegexError
    {
      regexobj = new Regex (ptn);  // パターンが不正な場合ここから例外が出る
      this.ptn = ptn;
    }
    /*
     * 入力された文字列を正規表現オブジェクトによりチェックして
     * パターンが見つからない場合にFindErrorを出す
     */
    public void check (string str) throws FindError
    {
      print ("checking \"" + ptn + "\" in \"" + str + "\" ... \n");
      /* 見つからない場合に例外を発生するようにする */
      if (!this.regexobj.match (str, 0))
        throw new FindError.PATTERN_NOT_FOUND ("Pattern \"%s\" not found in \"%s\"\n".printf (this.ptn, str));
    }
  }
  class MainClass
  {
    /* メイン処理 */
    public static int main (string[] args)
    {
      string str1 = "<img src=\"01.jpg\" alt=\"desc\" />";
      string str2 = "<img src=\"02.jpg\" />";
      string ptnstr = "alt=\"[^\"]+\"";
      //string ptnstr = "(a";  // 不正なパターン文字列のテスト用
      PatternChecker checker_imgalt;
      try
      {
        checker_imgalt = new PatternChecker (ptnstr);
      }
      catch (GLib.RegexError e)
      {
        GLib.critical ("Invalid regex pattern: \"%s\": %s", ptnstr, e.message);
        return 1;
      }
      /* 個別にtry-catchでチェックし、結果を表示 */
      try
      {
        checker_imgalt.check (str1);
        print ("OK\n");
      }
      catch (FindError e)
      {
        print ("NG\nFindError: %s", e.message);
      }

      try
      {
        checker_imgalt.check (str2);
        print ("OK\n");
      }
      catch (FindError e)
      {
        print ("NG\nFindError: %s", e.message);
      }

      for (int i = 0; i < 80; i++)
        print ("-");
      print ("\n");

      /*
        * try-catchがないところで例外が発生したらそこで中止
        * 「throws」のある関数をtry節なしで呼ぶと
        * コンパイル時に警告(unhandled error)も出る
        */
      checker_imgalt.check (str1);
      checker_imgalt.check (str2);

      /* 下のメッセージは表示されない */
      print ("All OK\n");

      return 0;
    }  // main
  }  // MainClass
}  // UserExceptionTest

下は実行結果。

checking "alt="[^"]+"" in "<img src="01.jpg" alt="desc" />" ... 
OK
checking "alt="[^"]+"" in "<img src="02.jpg" />" ... 
NG
FindError: Pattern "alt="[^"]+"" not found in "<img src="02.jpg" />"
--------------------------------------------------------------------------------
checking "alt="[^"]+"" in "<img src="01.jpg" alt="desc" />" ... 
checking "alt="[^"]+"" in "<img src="02.jpg" />" ... 

** (process:[プロセスID]): CRITICAL **: file [ビルドしたときの作業ディレクトリ]/userexceptiontest.vala.c: line 481: uncaught error: Pattern "alt="[^"]+"" not found in "<img src="02.jpg" />"

なお、正規表現オブジェクトは(バージョン2.14以上の)GLibの機能として標準で用意されている*1ため、Vala言語でも追加のパッケージなしで使用することができる。
使い方は文字列のサンプルの他、Valadocのページと、必要に応じてGLib(C言語)のリファレンス書式についても参照。

関連記事:

使用したバージョン:

  • Vala 0.7.2

*1:PCRE(「Perl互換の正規表現」の意)というライブラリを用いていて、Perl言語の正規表現と機能が互換