ochalog

Ruby と MediaWiki が好きな電子・情報系の学生のブログ。

鬼車のテスト

C で正規表現が使えるかのテスト。Ruby で使われているという鬼車を試してみた。応用先はまだ考えていないが。

以下は、鬼車公式の最小使用例(simple.c)を対話型にしてみたもの。正規表現が合っているかの確認くらいには使えるかも(自分の場合 Firefox のスクラッチパッドか irb を使うけど)。

/*
 * test-onig.c
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <readline/readline.h>
#include <oniguruma.h>
 
void print_onig_error(int, OnigErrorInfo*);
 
int main(void) {
    int r; /* 返り値 */
    char *start, *range, *end;
    regex_t *reg;
    OnigErrorInfo einfo;
    OnigRegion *region;
 
    char *str, *pattern;
 
    str = readline("文字列を入力してください\n> ");
    pattern = readline("正規表現パターンを入力してください\n> ");
 
    r = onig_new(&reg, pattern, pattern + strlen(pattern),
            ONIG_OPTION_DEFAULT, ONIG_ENCODING_UTF8, ONIG_SYNTAX_DEFAULT, &einfo);
    if (r != ONIG_NORMAL) {
        print_onig_error(r, &einfo);
    }
 
    region = onig_region_new();
 
    /* ここはアドレスの演算 */
    end = str + strlen(str);
    start = str;
    range = end;
 
    r = onig_search(reg, str, end, start, range, region, ONIG_OPTION_NONE);
    if (r >= 0) {
        int i, j;
        printf("位置 %d でマッチ\n", r);
        for (i = 0; i < region->num_regs; i++) {
            int beg = region->beg[i];
            int end = region->end[i]; /* マッチ終了文字 + 1 */
            int len = end - beg;
            char *match_str;
 
            match_str = (char*)calloc(len, sizeof(char));
            if (!match_str) {
                puts("メモリ確保に失敗しました");
                return 1;
            }
            for (j = 0; j < len; j++) {
                match_str[j] = str[beg + j];
            }
 
            printf("%d: %s (%d-%d)\n", i, match_str, beg, end - 1);
 
            free(match_str);
        }
    } else if (r == ONIG_MISMATCH) {
        puts("見つかりませんでした");
    } else {
        print_onig_error(r, NULL);
    }
 
    free(str);
    free(pattern);
    onig_region_free(region, 1);
    onig_free(reg);
    onig_end();
 
    return 0;
}
 
void print_onig_error(int r, OnigErrorInfo *einfo) {
    char s[ONIG_MAX_ERROR_MESSAGE_LEN];
 
    if (einfo) {
        onig_error_code_to_str(s, r, einfo);
    } else {
        onig_error_code_to_str(s, r);
    }
 
    printf("ERROR: %s\n", s);
 
    exit(1);
}

ビルドは

gcc -o test-onig test-onig.c -lreadline -lonig

で行える。