"buffer_editor": Buffer editor utility in C
hacker emblem Happy Hacking!


English Here (machine translation)

buffer_edit: 文字列バッファを正規表現ベースで編集するユーティリティ

この C 言語ユーティリティは、文字列バッファの内容を正規表現 (regular expression) で指定した内容で編集できます。編集した結果の文字列は動的メモリに割り付けられますので、呼び出し側で buffer_edit_free() を呼び出してバッファの解放を行う必要があります。

正規表現文字列と置き換え文字列の処理をあらかじめ行っておく必要がある場合には、buffer_edit_regcomp(), buffer_edit_FSM() そして buffer_edit_regfree() の API セットが使用できます。


API を使用するためのヘッダは buffer_editor.h で、API の実装は buffer_editor.c です。API の説明は、この文書で後述しています。
テスト・プログラム buffer_editor_test.c そして make ファイル Makefile も記述しました。


API の説明

  1. 正規表現により文字列バッファを編集するユーティリティ: buffer_edit()
    char *buffer_edit(char                  *src
    , size_t start_line_no
    , size_t end_line_no
    , Buffer_edit_command_e cmd
    , char *pattern1
    , int cflags
    , char *pattern2
    , char pattern2_delimit
    , int *regcomp_errcode
    , char *regcomp_errbuf
    , size_t regcomp_errbuf_size
    );
    int buffer_edit_free(char *edited_buffer)

    src には編集対象となる文字列を収めたバッファを指定します。
    start_line_no には編集対象になる行の最初の行番号 (1 以上) を指定します。
    enc_line_no には編集対象になる行の最後の行番号 (1 以上) を指定します。
    start_line_no にゼロを指定すると開始行番号は 1 とみなし、end_line_no にゼロを指定すると終了行番号は (size_t)-1 とみなします。
    cmd には次の編集コマンドの識別子のいずれかを指定します。

    1. Buffer_edit_cmd_extract :

      pattern1 に指定された正規表現文字列に一致する行を抽出します。pattern2 は無視します。

    2. Buffer_edit_cmd_delete :

      pattern1 に指定された正規表現文字列に一致する行を削除します。pattern2 は無視します。

    3. Buffer_edit_cmd_substitute :

      pattern1 に指定された正規表現文字列に一致するサブ・パターンを、pattern2 に指定された置き換え文字列に変換します。

    4. Buffer_edit_cmd_substitute_only :

      pattern1 に指定された正規表現文字列に一致するサブ・パターンを、pattern2 に指定された置き換え文字列に変換した結果だけを出力します。

    5. Buffer_edit_cmd_general_substitute :

      ある行の中で、pattern1 に指定された正規表現文字列に一致するすべてのサブ・パターンを、pattern2 に指定された置き換え文字列に変換します。

    6. Buffer_edit_cmd_general_substitute_only :

      ある行の中で、pattern1 に指定された正規表現文字列に一致するすべてのサブ・パターンを、pattern2 に指定された置き換え文字列に変換した結果だけを出力します。

    pattern1 には src の各行を検索する正規表現文字列パターンを指定します。

    cflags には、REG_BASIC あるいは REG_EXTENDED と REG_ICASE の論理和 (REG_BASIC, REG_BASIC | REG_ICASE, REG_EXTENDED, REG_EXTENDED | REG_ICASE) を指定します。REG_BASIC は POSIX.2 の「基本」表現 ("basuc RE") にあたり、ed(1) Unix コマンドのものとほぼ同じ正規表現を pattern1 で使用する場合に指定します。
    REG_EXTENDED は POSIX.2 の「拡張」表現 ("extended RE") にあたり、egrep(1) Unix コマンドのものとほぼ同じ正規表現を pattern1 に使用する場合に指定します。
    REG_ICASE は大文字と小文字を区別しない場合に指定します。

    pattern2 には、置き換え文字列を sed(1) に似た形式で指定します。例えば、pattern1 が ",(def|iii),(.*),(jkl|vi)," であるとして、これに一致した行全体を指定するには "\0" (あるいは、"\0") と記述します。
    また、pattern1 で括弧 ('(' と ')') で囲んだサブ・パターンそれぞれは、"\1" (= (def|iii)), "\2" (= (.*)), "\3\" (=(jkl|vi)) といったように、サブ・パターンの出現順序を示す数列を区切り文字の後に続けて記述します。

    pattern2_delimit には、pattern2 でサブ・パターンを指定する区切り文字に使用する ASCII 文字コードを指定します。nil 文字 ('\0') を指定した場合は、サブ・パターン指定の区切り文字はバックスラッシュ ('\\') になります。

    regcomp_errcode には、pattern1 文字列を regcomp(3) で処理した際に発生したエラーのエラーコードを出力する整数のアドレスを渡します。
    regcomp_errbuf には、regcomp(3) での処理エラーの内容を示す文字列を出力するバッファのアドレスを渡します。
    regcomp_errbuf_size には regcomp_errbuf が指すバッファのサイズを指定します。

    正常終了した場合、編集結果の文字列を内容にもつ新たに動的獲得されたバッファのアドレスを、戻り値に返します。
    なんらかのエラーが発生した場合は、NULL が戻り値に返ります。発生したエラーの詳細は以下のように errno に出力されます。

    1. EINVAL (= 22) : 不正な引数が渡された場合
    2. ENOMEM (= 12) : 作業メモリに割り当てる動的メモリが獲得できない場合 (システムメモリ不足)
    3. ERANGE (= 34) : pattern2 に記述されたサブ・パターン指定数が unsigned long 型が取りうる最大値を超えている場合

    buffer_edit() の戻り値に返されたアドレスは動的に獲得されたバッファのものなので、buffer_edit_free() で明示的にメモリ開放する必要があります。
    buffer_edit_free() は正常終了した場合はゼロを返し、エラーが発生した場合は非ゼロを返します。

  2. 正規表現により文字列バッファを編集するユーティリティ(2): buffer_edit_FSM()
    Buffer_edit_FSM_t buffer_edit_regcomp(char   *pattern1
    , int cflags
    , char *pattern2
    , char pattern2_delimit
    , int *regcomp_errcode
    , char *regcomp_errbuf
    , size_t regcomp_errbuf_size
    );
    char *buffer_edit_FSM(char                  *src
    , size_t start_line_no
    , size_t end_line_no
    , Buffer_edit_command_e cmd
    , Buffer_edit_FSM_t regex
    );
    int buffer_edit_regfree(Buffer_edit_FSM_t regex);

    buffer_edit_regcomp() は、pattern1 に指定された正規表現を cflags に指定された修飾子 (REG_BASIC, REG_BASIC|REG_ICASE, REG_EXTENDED, REG_EXTENDED|REG_ICASE のいずれか) で regcomp(3) 処理した結果と、(NULL ではない) pattern2 に指定された置き換え文字列を処理した結果を収めた動的メモリ上のデータ構造アドレスを返します。
    正規表現文字列あるいは置き換え文字列の処理でエラーが発生した場合は、NULL を返します。
    NULL 以外のアドレスが返された場合、buffer_edit_regfree() で明示的に動的メモリを開放する必要があります。

    buffer_edit_FSM() は、buffer_edit_regcomp() が返した正規表現と置き換え文字列の処理結果データ構造 regex を参照して、start_line_no から end_line_no で指定される src 文字列中の行を編集した結果を収めた動的メモリ上の文字列バッファ・アドレスを返します。
    編集処理でエラーが発生した場合には、NULL を返します。

    buffer_edit_regfree() は、buffer_edit_regcomp() で獲得された動的メモリ上のデータ構造を解放します。
    正常終了した場合にはゼロを、エラーが発生した場合には非ゼロを返します。

    API それぞれの引数の意味と errno に出力されるエラー詳細は、buffer_edit() のものと同様です。