この文書では、SUFARY の C ライブラリの使い方について解説します。 array ファイル、DocID ファイルについてご存知ない方は、 先に「検索用ファイル作成ガイド」をお読み下さい。
C プログラムから SUFARY を使うには、まず sufary.h
を
インクルードします。
// sample.c //
#include <stdio.h> #include <stdlib.h> #include "sufary.h" ...
そして、以下のようにコンパイルします。
// コンパイル //
% $SUFARY/libtool --mode=link gcc -I$SUFARY/lib -o sample sample.c \ $SUFARY/lib/libsufary.la or % gcc -I$SUFARY/lib -o sample sample.c $SUFARY/lib/libsufary.a
$SUFARY/src/
に C ライブラリを用いたプログラムが
ありますので、参考にして下さい。
SUFARY *sa_open(char *text_file_name, char *array_file_name)
// 例 //
/* data.txt -> data.txt.ary */ SUFARY *ary = sa_open("data.txt", NULL);ファイルを開くのに成功した場合は、 SUFARY 型変数へのポインタを、失敗した場合は NULL を返します。 SUFARY 型変数は検索時に必ず必要になります。
void sa_close(SUFARY *ary)
SA_INDEX sa_get_array_size(SUFARY *ary)
SA_INDEX sa_get_text_size(SUFARY *ary)
SUF_RESULT sa_find(SUFARY *ary, SA_INDEX left, SA_INDEX right, char *keyword, int keyword_length, int base_txt_skip)
keyword
でキーワードを、
keyword_length
でキーワードの長さ ( 大抵の場合は
strlen(keyword)
) を指定します。
left
, right
は検索する範囲を表します。
「0 から suffix array のサイズ ( sa_get_array_size(ary)
) - 1」まで
の値を取ることができます。
base_txt_skip
は、
テキスト側の比較開始位置を base_txt_skip
文字後ろにずらします。
特殊なことをしない限り 0 を指定します。
// SUF_RESULT //
typedef struct { SUFARY *suf; SA_INDEX left; SA_INDEX right; SA_STAT stat; } SUF_RESULT;
// 例:一般的な使い方 //
char *key = "hello"; SUF_RESULT sr = sa_find(ary, 0, sa_get_array_size(ary) - 1, key, strlen(key), 0);キーワードの見つかった場所は範囲で表されます。 これらは
sr.left
と sr.right
に格納されます。
キーワードにマッチする文字列が見つからなければ
sr.stat
に FAIL が、
見つかれば SUCCESS が格納されます。
suffix array ( array ファイル ) の各要素にはテキスト位置情報 ( テキストの先頭からの文字数 ) が格納されています。 検索結果は suffix array の添字の情報だけです。 文字列として扱うためには、 これをテキスト位置、文字列ポインタに変換する関数が必要となります。
SA_INDEX sa_aryidx2txtidx(SUFARY *ary, SA_INDEX i)
char *sa_aryidx2txtptr(SUFARY *ary, SA_INDEX i)
char *sa_txtidx2txtptr(SUFARY *ary, SA_INDEX i)
テキスト位置を元に検索結果を文字列として取り出す関数もいくつか 用意してあります。
SA_STRING sa_seek_context_lines(const SUFARY *ary, char *pos, int bkwrd, int frwrd)
pos
を含む一行と、その前の bkwrd
行、
後の frwrd
行を SA_STRING
型として取り出します。
// SA_STRING //
typedef struct { char *ptr; size_t len; } SA_STRING;
SA_STRING sa_seek_context_region(const SUFARY *ary, char *pos, const SA_STRING begin_tag, const SA_STRING end_tag)
begin_tag
, end_tag
) で囲まれた文字列を取り出します。
指定されたテキスト位置の前後をスキャンしてタグを探すという単純な方法なので、
DocID ファイルは必要有りませんが、
DocID ファイルを用いる方法より遅くなります。
size_t sa_copy_region(char *dst, const SA_STRING src)
str
を dst
にコピーし、末尾にナル文字
を追加します。dst
は src.len + 1
バイト確保
されている必要があります。
char *sa_dup_region(const SA_STRING src)
malloc
でメモリを確保して、文字列 str
コピー
し末尾にナル文字を追加します。
// sample.c //
#include <stdio.h> #include <stdlib.h> #include "sufary.h" int main(int argc, char *argv[]) { SUFARY *ary; SUF_RESULT sr; ary = sa_open(argv[2], NULL); if (ary == NULL) exit(1); sa_set_debug_mode(1); sr = sa_find(ary, 0, sa_get_array_size(ary) - 1, argv[1], strlen(argv[1]), 0); printf("%ld %ld\n", sr.left, sr.right); if (sr.stat == SUCCESS) { SA_INDEX tmp; for (tmp = sr.left; tmp <= sr.right; tmp++) { /* '<=' に注意 */ SA_INDEX index = sa_aryidx2txtidx(ary, tmp); char *pointer = sa_aryidx2txtptr(ary, tmp); SA_STRING str, btag, etag; char *txt_ptr; printf("★テキストファイルの %ld 文字目からマッチ\n", index); printf("★先頭二文字表示(1)\n%.*s\n", 2, pointer); str.ptr = pointer; str.len = 2; txt_ptr = malloc(3); sa_copy_region(txt_ptr, str); printf("★先頭二文字表示(2)\n%s\n", txt_ptr); free(txt_ptr); txt_ptr = sa_dup_region(str); printf("★先頭二文字表示(3)\n%s\n", txt_ptr); free(txt_ptr); str = sa_seek_context_lines(ary, pointer, 0, 0); printf("★一行表示\n%.*s\n", str.len, str.ptr); str = sa_seek_context_lines(ary, pointer, 1, 1); printf("★前後の一行も表示\n%.*s\n", str.len, str.ptr); btag.ptr = "<DOC>"; btag.len = 5; etag.ptr = "</DOC>"); etag.len = 6; str = sa_seek_context_region(ary, pointer, btag, etag); printf("★DOC タグに囲まれた領域を表示\n%.*s\n", str.len, str.ptr); } } sa_close(ary); return 0; }
注意: 正規表現検索周りはまだ作業中のため 今後仕様が著しく変更される可能性があります。
SA_RESULT_LIST *sa_regex(SUFARY * ary, SA_INDEX left, SA_INDEX right, char *keyword, int keyword_length)
keyword
でキーワードを、
keyword_length
でキーワードの長さ ( 大抵の場合は
strlen(keyword)
) を指定します。
left
, right
は検索する範囲を表します。
0 から「suffix array のサイズ ( sa_get_array_size(ary)
) - 1」まで
の値を取ることができます。
SA_RESULT_LIST *sa_ignore_case(SUFARY * ary, SA_INDEX left, SA_INDEX right, char *keyword, int keyword_length)
keyword
でキーワードを、
keyword_length
でキーワードの長さ ( 大抵の場合は
strlen(keyword)
) を指定します。
left
, right
は検索する範囲を表します。
0 から「suffix array のサイズ ( sa_get_array_size(ary)
) - 1」まで
の値を取ることができます。
void sa_free_result_list(SA_RESULT_LIST *listp)
DID *sa_open_did(char *file_name)
sa_close_did(DID *did)
DID_RESULT sa_didsearch(DID *did, SA_INDEX target)
target
が含まれるテキストエリアの
開始位置 ( start
)、
大きさ ( size
)、
通し番号 ( no
) 等の情報を取ってきて、
DID_RESULT 型変数に格納します。
// DID_RESULT //
typedef struct { SA_INDEX start; SA_INDEX size; SA_INDEX no; SA_STAT stat; } DID_RESULT;該当するテキストエリアがなければ、
stat
に FAIL が、あれば SUCCESS が入ります。
// 例 //
DID_RESULT dr = sa_didsearch(did, 192); if (dr.stat == SUCCESS) printf("no. %ld, start %ld, size %ld\n", dr.no, dr.start, dr.size);
SA_INDEX sa_get_start_position(DID *did, SA_INDEX i)
i
番目のテキストエリアの開始位置位置を得ます。
SA_INDEX sa_get_end_position(DID *did, SA_INDEX i)
i
番目のテキストエリアの終了位置を得ます。
SA_INDEX sa_get_did_size(DID *did)
// 例:全テキストエリアを表示 //
for (i = 0; i > sa_get_did_size(did); i++) { SA_INDEX doc_start = sa_get_start_position(did, i); SA_INDEX doc_end = sa_get_end_position(did, i); printf("-- Text Area No. %ld\n%.*s\n", i, doc_end - doc_start, sa_txtidx2txtptr(ary, doc_start)); }
// sample-did.c //
#include <stdio.h> #include <stdlib.h> #include "sufary.h" int main(int argc, char *argv[]) { SUFARY *ary; DID *did; SUF_RESULT sr; ary = sa_open(argv[2], NULL); did = sa_open_did(argv[3]); if (ary == NULL || did == NULL) exit(1); printf("★いくつあるかな ... %ld\n", sa_get_did_size(did)); sr = sa_find(ary, 0, sa_get_array_size(ary) - 1, argv[1], strlen(argv[1]), 0); if (sr.stat == SUCCESS) { SA_INDEX tmp; for (tmp = sr.left; tmp <= sr.right; tmp++) { /* '<=' に注意 */ SA_INDEX pos = sa_aryidx2txtidx(ary, tmp); DID_RESULT dr = sa_didsearch(did, pos); if (dr.stat == FAIL) continue; printf("★ no. %ld, start %ld, size %ld\n", dr.no, dr.start, dr.size); printf("★テキストエリア表示(1)\n"); printf("%.*s\n", dr.size, sa_txtidx2txtptr(ary, dr.start)); printf("★テキストエリア表示(2)\n"); printf("%.*s\n", dr.size, sa_txtidx2txtptr(ary, sa_get_start_position(did, dr.no))); } } sa_close_did(did); sa_close(ary); return 0; }
version 2.1.x から 3.x へ移行する際に、 マイナーバージョンアップではできないような大幅な仕様変更を行いました。
long sa_left(SUFARY *)
,
long sa_left(SUFARY *)
は廃止されました。
代わりに、
sr.left
, sr.right
を使用します
( sr
を SUF_RESULT 型の変数とする )
。
long sa_doc_start(DID *)
,
long sa_doc_size(DID *)
,
long sa_doc_no(DID *)
は廃止されました。
代わりに、
dr.start
, dr.size
, dr.no
を使用します
( dr
を DID_RESULT 型の変数とする )
。
sa_didsearch(DID *, SA_INDEX)
の返し値も void
から DID_RESULT
に変わりました。
eresult sa_sel(SUFARY *, char *)
,
eresult sa_search(SUFARY *, char *, int, int)
は廃止されました。
代わりに
SUF_RESULT sa_find(SUFARY *, SA_INDEX, SA_INDEX, char *, int, int)
を使って下さい。
long *sa_common_prefix_search(SUFARY *, char *, char)
はライブラリレベルでは必要ではないと判断し廃止しました。
検索の初期化関数 void sa_reset(SUFARY *)
は
検索結果構造体 SUF_RESULT の登場により不要となったので
廃止しました。
Version 2.1.x | Version 3.x |
sa_getline | |
sa_getlines | sa_seek_context_lines |
sa_getblock | sa_seek_context_region |
sa_getstr | |
sa_openfiles | sa_open |
sa_closefiles | sa_close |
sa_opendid | sa_open_did |
sa_closedid | sa_close_did |
sa_did_size | sa_get_did_size |
eresult | SA_STAT |