最終更新日: 2002-09-18
file_name のファイルに対して、 UTF-8エンコーディングの文字単 位で Suffix Arrayを作成し、ファイル (file_name.ary) に格納す る。より詳しい例は mksary.c を参 照のこと。
#include <stdlib.h> #include <errno.h> #include <sary.h> int main (int argc, char **argv) { char *file_name; SaryInt ipoints; gboolean status; SaryBuilder *builder; if (argc != 2) exit(2); file_name = argv[1]; builder = sary_builder_new(file_name); sary_builder_set_ipoint_func(builder, sary_ipoint_char_utf8); ipoints = sary_builder_index(builder); if (ipoints == -1) { g_print("error: %s(.ary): %s\n", file_name, g_strerror(errno)); exit(2); } status = sary_builder_sort(builder); if (status == FALSE) { g_print("error: %s(.ary): %s\n", file_name, g_strerror(errno)); exit(2); } sary_builder_destroy(builder); return 0; }
file_name のファイルに対して、pattern で検索を行い、検索結果 を出現位置順にソートし、行単位で表示する。検索には file_name 用に構築された Suffix Array が必須。より詳しい例は sary.c を参照のこと。
#include <stdlib.h> #include <errno.h> #include <sary.h> int main (int argc, char **argv) { Saryer *searcher; char *pattern; char *file_name; if (argc != 3) exit(2); pattern = argv[1]; file_name = argv[2]; searcher = saryer_new(file_name); if (searcher == NULL) { g_print("error: %s(.ary): %s\n", file_name, g_strerror(errno)); exit(2); } if (saryer_search(searcher, pattern)) { gchar *line; saryer_sort_occurrences(searcher); while ((line = saryer_get_next_line(searcher))) { g_print("%s", line); g_free(line); } } saryer_destroy(searcher); return 0; }
libsary を用いたプログラム program.c をコンパイルするには次 のように実行します。本格的な開発には autoconf, automake, libtool の利用をお勧めします。
% gcc program.c -o program `sary-config --libs` `sary-config --cflags`
SaryBuilder* sary_builder_new (const gchar *file_name)
SaryBuilder* sary_builder_new2 (const gchar *file_name,
const gchar *array_name);
void sary_builder_destroy (SaryBuilder *builder);
void sary_builder_set_ipoint_func (SaryBuilder *builder,
SaryIpointFunc ipoint_func);
SaryInt sary_builder_index (SaryBuilder *builder);
gboolean sary_builder_sort (SaryBuilder *builder);
gboolean sary_builder_block_sort (SaryBuilder *builder);
void sary_builder_set_block_size (SaryBuilder *builder,
SaryInt block_size);
void sary_builder_set_nthreads (SaryBuilder *builder,
SaryInt nthreads);
void sary_builder_connect_progress (SaryBuilder *builder,
SaryProgressFunc
progress_func,
gpointer progress_func_data);
gchar* sary_ipoint_char_ascii (SaryText *text)
gchar* sary_ipoint_char_eucjp (SaryText *text)
gchar* sary_ipoint_char_sjis (SaryText *text)
gchar* sary_ipoint_char_utf8 (SaryText *text)
gchar* sary_ipoint_line (SaryText *text)
注意: saryer_search2, saryer_get_next_line2, saryer_get_next_context_lines2, saryer_get_next_tagged_region2 はスクリプト言語用のバンディ ングを書く人、あるいは効率に熱心な人のために用意されています。 これらの関数では文字列は長さとともに扱われるため、'\0' 文字 を中に含んでも構いません。新しい文字列が生成されることはあり ません。
Saryer* saryer_new (const gchar
*file_name)
Saryer* saryer_new2 (const gchar *file_name,
const gchar *array_name)
void saryer_destroy (Saryer *saryer)
void saryer_enable_cache (Saryer *saryer)
gboolean saryer_search (Saryer *saryer,
const gchar *pattern)
gboolean saryer_search2 (Saryer *saryer,
const gchar *pattern,
SaryInt len)
gboolean saryer_isearch (Saryer *saryer,
const gchar *pattern,
SaryInt len)
gboolean saryer_isearch_reset (Saryer *saryer)
gboolean saryer_icase_search (Saryer *saryer,
const gchar *pattern)
gboolean saryer_icase_search2 (Saryer *saryer,
const gchar *pattern,
SaryInt len)
SaryText* saryer_get_text (Saryer *saryer)
SaryMmap* saryer_get_array (Saryer *saryer)
gchar* saryer_get_next_line (Saryer *saryer)
gchar* saryer_get_next_line2 (Saryer *saryer,
SaryInt *len)
gchar* saryer_get_next_context_lines (Saryer *saryer,
SaryInt backward,
SaryInt forward)
gchar* saryer_get_next_context_lines2 (Saryer *saryer,
SaryInt backward,
SaryInt forward,
SaryInt *len)
gchar* saryer_get_next_tagged_region (Saryer *saryer,
const gchar *start_tag,
const gchar *end_tag)
gchar* saryer_get_next_tagged_region2 (Saryer *saryer,
const gchar *start_tag,
SaryInt start_tag_len,
const gchar *end_tag,
SaryInt end_tag_len,
SaryInt *len)
SaryText* saryer_get_next_occurrence (Saryer *saryer)
gchar* saryer_peek_next_occurrence_position (Saryer *saryer)
SaryInt saryer_count_occurrences (Saryer *saryer)
void saryer_sort_occurrences (Saryer *saryer)
テキスト処理には SaryText オブジェクトを利用します。このオブ ジェクトはカーソルという状態を持っており、オブジェクトに対す る操作はこのカーソルを元にして行われます。
SaryText* sary_text_new (const gchar *file_name)
void sary_text_destroy (SaryText *text)
SaryInt sary_text_get_lineno (SaryText *text)
void sary_text_set_lineno (SaryText *text,
SaryInt lineno)
SaryInt sary_text_get_linelen (SaryText *text)
gchar* sary_text_get_line (SaryText *text)
gchar* sary_text_get_region (SaryText *cursor,
SaryInt len)
gboolean sary_text_is_eof (SaryText *text)
gchar* sary_text_get_cursor (SaryText *text)
void sary_text_set_cursor (SaryText *text,
gchar *cursor)
gchar* sary_text_get_bof (SaryText *text)
gchar* sary_text_get_eof (SaryText *text)
gchar* sary_text_goto_bol (SaryText *text)
gchar* sary_text_goto_eol (SaryText *text)
gchar* sary_text_goto_next_line (SaryText *text)
gchar* sary_text_goto_next_word (SaryText *text)
gchar* sary_text_forward_cursor (SaryText *text,
SaryInt len)
gchar* sary_text_backward_cursor (SaryText *text,
SaryInt len)
mksary.c の progress_bar 関数を参考にしてください。
インデックスポイントの割り当ては Perl などのスクリプト言語で 簡単に行うことができます。複雑なテキスト処理を要するときはス クリプト言語を利用すると便利です。次の例は行頭にインデックス ポイントを割り当てる例です。
% cat line-indexer.pl $offset = 0; while (<>) { print pack 'N', $offset; $offset += length; } % perl line-indexer.pl foobar.txt > foobar.txt.ary
このようにして作成した foobar.txt.ary ファイルを mksary -s でソートすれば、 Suffix Array が完成します。
% mksary -s foobar.txt
$Id: libsary.html,v 1.32 2002/09/18 06:20:59 satoru Exp $
satoru@namazu.org