"buffer_checker": Buffer Checking Library using `regex(3C)'
hacker emblem Happy Hacking!


English Here (machine translation)

buffer_checker: 正規表現を利用した入出力バッファ・チェック・ライブラリ

この C 言語ライブラリは、受信(入力)バッファのフィールド内容を判断し適切な処理を施す場合や、サービス機能を実行した結果の送信(出力)バッファの内容を確認する場合に、正規表現 regexe(3C) を利用することを目的とした「バッファ・チェッカ」です。不正な文字コードがフィールドに入力されていないことをバッファを処理に回す前に確認することを、定型的で宣言的なスタイルで行うことを狙いとしています。

API を使用するためのヘッダは buffer_checker.h で、API の実装は buffer_checker.c です。
また、テスト用のプログラムとして test.c も記述しました。このテスト・プログラムで、氏名、住所、メールアドレスなどの文字列フィールドが規定の正規表現に一致するか否かを判定するケース、そして、整数値フィールドをユーザ定義のコールバック関数で判定するケースでの、当 API 利用方法を示します。

別の API 利用例として、正整数列の総和を求めるプログラム TM_sum.c と、万能チューリング・マシン UTM.c および UTM 上での総和計算プログラム TM_sum.ksh も作成しました。
UTM をプログラミングするために必要な UTM マシン語とコマンド・オプションの簡単な説明は UTM.usage.txt にあります。

これらのソースコードをコンパイルするために Makefile を使用しました。

ライセンスは GNU Public License とします。

API の説明

  1. API で予約済みのエラーコード Buffer_checker_result_t

    この API 戻り値で予約済みのエラーコード 14 個を buffer_checker.h で定義しています。それぞれのコード値とその意味は下表のとおりです。

    シンボル意味
    BCR_Continue-2147483648次のフィールドへ進む (正常)
    BCR_Terminate-2147483647チェック終了 (正常)
    BCR_Unmatched-2147483646正規表現と一致しない
    BCR_Illegal_args-2147483645API への引数が不正
    BCR_Illegal_defines-2147483644Buffer_checker_t 構造体の内容が不正
    BCR_Cannot_allocate_preg-2147483643正規表現コンパイル regcomp(3C) 用の領域獲得に失敗した
    BCR_Failed_to_compile_regex-2147483642正規表現コンパイル regcomp(3C) に失敗した
    BCR_Not_initialized_defines-2147483641Buffer_checker_t 構造体が初期化されていない
    (API を使用するには、まず init_buffer_checker() を呼び出す必要があります)
    BCR_Cannot_get_field_addr-2147483640フィールドのアドレス取得に失敗した
    BCR_Field_runs_over_buffer-2147483639フィールドの領域がバッファの領域を超過している
    BCR_Field_size_is_illegal-2147483638フィールドのサイズが 0 になっている
    BCR_Field_string_is_too_long-2147483637正規表現と比較される文字列フィールドの文字列長がフィールドのサイズ以上になっている
    BCR_Broken_Configuration-2147483636Buffer_checker_t 構造体が壊れている
    BCR_Out_of_range_cond_cb_returns-2147483635Buffer_checker_t の cond_cb コールバックからの戻り値が clause_cbs[] 配列のインデックス範囲外になっている

    Buffer_checker_t の clause_cbs[] 配列に指定されたコールバック関数は、上表で予約されているもの以外の負数をそれ自身のエラーコードとして自由に使用できます。
    ・0 および正整数をclause_cbs[] コールバックが返した場合、API exec_buffer_checker() は、それらの値を Buffer_checker_t 構造体の次のインデックスとして解釈します。

  2. バッファ・フィールドのチェック方式を構成する Buffer_checker_t

    バッファ・フィールドごとのチェック方式 (バッファ上のフィールド・オフセット位置、サイズ、正規表現、各種コールバック関数) を指定する構成定義用の構造体です。
    この構造体は init_buffer_checker() で初期化 (定義の正当性確認、正規表現のコンパイルなど) された後、exec_buffer_checker() で通信バッファのフィールド・チェックを行う際に参照されます。構成内容を破棄するには finish_buffer_checker() を呼び出す必要があります。

    Buffer_checker_t 構造体メンバのシンボル名、型、意味は下表のとおりです。

    シンボル意味
    fld_offsetssize_tフィールドのバッファ内オフセット位置 (符号付)
    fldszsize_tフィールドのサイズ (符号なし)
    user_get_fld_addrvoid *(*)(
    void *buffer
    , ssize_t fld_offset
    , size_t *fldszp
    , void *user_cntxt
    )
    フィールドのアドレスを取得するコールバック関数のアドレス
    buffer -- バッファのアドレス
    fld_offset -- フィールドのオフセット位置
    fldszp -- フィールド・サイズを出力するアドレス
    user_cntxt -- すべてのコールバックに引き渡されコンテクスト情報のアドレス

    戻り値はフィールドのアドレスあるいは NULL でなければいけません。

    regexchar *正規表現を表す文字列
    pregregex_t *init_buffer_checker() 内で regcomp(3C) を使用して正規表現 regex をコンパイルした結果が展開されます。init_buffer_checker() を呼び出す前には、NULL でなければいけません。
    cond_cbssize_t (*)(
    size_t checker_index
    , void *buffer
    , size_t buffer_sz
    , void *fldp
    , Buffer_checker_regex_result_t regex_result
    , void *user_cntxt
    )
    フィールド内容確認コールバック関数のアドレス
    checker_index -- フィールド定義列のインデックス
    buffer -- バッファのアドレス
    buffer_sz -- バッファのサイズ
    fldp -- フィールドのアドレス
    regex_result -- 正規表現判定 regexex(3C) の結果

    BCRR_Matched -- regex とフィールドは一致しています
    BCRR_Unmatched -- regex とフィールドは一致していません
    BCRR_Not_Specified_Regex -- regex は指定されていません (NULL が指定されている場合)

    user_cntxt -- すべてのコールバックに引き渡されるコンテクスト情報のアドレス

    戻り値は 0, 1 , 2 のいずれかでなければいけません。

    clause_cbsint (*[3])(
    size_t checker_index
    , void *buffer
    , size_t buffer_sz
    , void *fldp
    , void *user_cntxt
    )
    フィールド内容処理コールバック関数へのアドレス
    checker_index -- フィールド定義列のインデックス
    buffer -- バッファのアドレス
    buffer_sz -- バッファのサイズ
    fldp -- フィールドのアドレス
    user_cntxt -- すべてのコールバックに引き渡されるコンテクスト情報のアドレス

    戻り値が 0 または正定数の場合、exec_buffer_checker() により次に検査されるフィールド定義列のインデックスとして解釈されます。また、Buffer_checker_result_t で予約されているもの以外の負数をユーザ定義のエラーコードとして自由に使用できます。

    バッファ・フィールド定義を構造体初期化記述で行う際に便利なように、以下の 4 つのマクロを定義してあります。

    • フィールド位置とサイズの設定
      Buffer_checker_fld(S,F) 

      Buffer_checker_t 構造体の初期化記述中に使用して、フィールドのオフセット位置 fld_offset とサイズ fldsz を設定します。
      構造体の型名を第 1 引数 S に、フィールドに対応するメンバ名を第 2 引数 F に渡します。

    • 正規表現のみをチェックに使用するフィールドの場合
      Buffer_checker_RE(RE,MATCHED_CB,UNMATCHED_CB)
      		

      Buffer_checker_t構造体の初期化記述中に使用して、第 1 引数 RE を正規表現 regex に、第 2 引数 MATCHED_CB を正規表現一致時コールバック clause_cbs[0] に、第 3 引数 UNMATCHED_CB を不一致時コールバック clause_cbs[1] に設定します。

    • 空文字列を含むすべての文字列を受け付けるフィールドの場合
      Buffer_checker_ANY_MATCH_RE(MATCHED_CB)
      		

      Buffer_checker_t構造体の初期化記述中に使用して、すべての文字列と一致する正規表現 "^.*$" を regex に、フィールド文字列をコールバックされる関数のアドレス (第 1 引数 MATCHED_CB) を clause_cbs[0] に設定します。

    • 数値型フィールドやサブ構造体などの正規表現以外のフィールド内容検査手順を必要とする場合
      Buffer_checker_COND(RE,COND_CB,NEG_CB,EQ_CB,POSI_CB)
      		

      Buffer_checker_t構造体の初期化記述中に使用して、文字列として評価した場合の正規表現 (第 1 引数 RE) (フィールドを文字列として評価する必要がない場合、第 1 引数 RE には NULL) を regex に、フィールド内容検査コールバック関数のアドレス (第 2 引数 COND_CB) を cond_cb に、コールバックの戻り値が 0 の場合のフィールド処理関数アドレス (第 3 引数 NEG_CB) を cluase_cbs[0] に、戻り値が 1 の場合のフィールド処理関数アドレス (第 4 引数 EQ_CB) を clause_cbs[1] に、戻り値が 2 の場合のフィールド処理関数アドレス (第 5 引数 POSI_CB) を cluase_cbs[2] に設定します。


  3. フィールド定義構造の初期化
    Buffer_checker_result_t init_buffer_checker(
    Buffer_checker_t *defines
    , size_t defines_cnt
    , size_t buffer_sz
    , Regex_preg_list_t *regex_preg_list
    )

    フィールドの検査方式を定義した Buffer_checker_t 構造体を検証し初期化します。正規表現 regex が与えられている場合は、それを regcomp(3C) でコンパイルした結果を動的に獲得したメモリ領域に展開し、preg にそのアドレスを設定します。

    • defines -- フィールド検査方式構成を定義した Buffer_checker_t 構造体のアドレス
    • defines_cnt -- defines で定義されているフィールド検査方式の数
    • buffer_sz -- この構成で検査されるバッファのサイズ
    • regex_preg_list -- 正規表現 regex とコンパイル済みの正規表現の対を収める構造

    戻り値として BCR_Illegal_args, BCR_Illegal_defines, BCR_Continue, BCR_Cannot_allocate_preg, BCR_Failed_to_compile_regex を返します。BCR_Continue 以外が戻された場合、finish_buffer_checker() を使用して Buffer_checker_t 構造体で獲得したメモリを解放する必要があります。

  4. バッファのフィールド検査と内容処理コールバック呼び出し
    Buffer_checker_result_t exec_buffer_checker(
    void *buffer
    , size_t buffer_sz
    , Buffer_checker_t *defines
    , size_t defines_cnt
    , void *user_cntxt
    , size_t *executed_cnt
    )

    init_buffer_checker()により初期化されたフィールド検査方式定義 defines を参照して、バッファのフィールドそれぞれを検査し、検査結果に相当するフィールド内容処理コールバックを呼び出します。処理されたフィールドの個数を executed_cnt に出力します。

    • buffer -- バッファのアドレス
    • buffer_sz -- バッファのサイズ
    • defines -- 初期化済みフィールド定義のアドレス
    • defines_cnt -- フィールド定義の数
    • user_cntxt -- すべてのコールバックに引き渡されるコンテクスト情報のアドレス
    • executed_cnt -- 処理されたバッファ上のフィールド数を出力するアドレス

    戻り値として BCR_Continue, BCR_Illegal_args, BCR_Broken_Configuration, BCR_Cannot_get_field_addr, BCR_Field_size_is_illegal, BCR_Field_runs_over_buffer, BCR_Field_string_is_too_long, BCR_Out_of_range_cond_cb_returns およびユーザ定義のエラーコード (負正数) を返します。BCR_Continue 以外が戻された場合、finish_buffer_checker() を使用して Buffer_checker_t 構造体で獲得したメモリを解放する必要があります。

  5. API 使用の終了: フィールド定義構造の破棄
    Buffer_checker_result_t finish_buffer_checker(
    Buffer_checker_t *defines
    , ssize_t defines_cnt
    , Regex_preg_list_t *regex_preg_list
    )

    API の使用を終了するために、init_buffer_checker() で獲得されたメモリ領域などの資源解放を行います。

    • defines -- 初期化済みフィールド定義のアドレス
    • defines_cnt -- フィールド定義の数
    • init_buffer_checker() を呼び出して設定した正規表現 regex とそのコンパイル結果の対を収めた構造 regexe_preg_list を渡します。

    戻り値として、BCR_Continue, BCR_Illegal_args を返します。