* Senna API解説

Sennaの全ての機能はAPI関数を通して提供されます。

APIは、basic API, advanced API, low-level APIの3種類から構成されます。
basic APIを使ってインデックスの作成・更新・検索の一通りの機能を使用できます。
advanced APIを用いることによって、検索精度の細かなチューニングを制御することが可能になります。
low-level APIを用いることによってSennaの内部のデータ構造にアクセスし、さらに複雑なデータの操作や検索処理が行えます。

* basic API

basic APIは、2つのデータ型とその操作関数、およびsennaライブラリを初期化する関数とで構成されます。2つのデータ型とは、インデックスファイルに対応するsen_index型と、
検索結果に対応するsen_records型です。

** Senna初期化関数

 sen_rc sen_init(void);

Sennaの機能を使用する前に初期化関数sen_init()をプロセス毎に一度だけ呼び出す必要があります。
(マルチスレッドアプリケーションの場合、いずれかのスレッドで一度だけ実行すれば十分です。)

 sen_rc sen_fin(void);

Sennaの利用をやめる場合に呼び出します。

** sen_index 型

文字列から文書を高速に検索するための転置インデックス(索引)ファイルに対応するデータ型です。
文書IDと文書内容(文字列)のペアからなる文書を登録すると、
文字列をキーとして、これを含む文書IDの集合を高速に取り出すことができます。
sen_indexのインスタンスはファイルシステム上の特定のファイルに対応しており、格納された文書は永続的に保存されます。
ただし、sen_indexを用いて、文書IDに対応する文書内容を取り出すことはできません。

文書IDには固定長のバイナリデータか、nulで終端する可変長の文字列が使用できます。

複数の文書で文書IDが重複してはいけません。

最大文書ID長は8191バイトです。

値にはnulで終端する可変長の文字列を指定します。

値には最大長の制限はありません。

値に指定する文字列のエンコーディングは、SHIFT-JIS, EUC-japan, utf-8のいず
れかを選択できます。

値に指定する文字列の分かち書き方式は、形態素解析, N-gramのどちらかを選択できます。

N-gramを選択した場合、英数文字列および記号文字列を文字要素に分割するか/しないかを
選択できます。

値に指定する文字列に対して、英文字の大文字/小文字、全角文字/半角文字の正規化処理を
行うか/行わないかを選択できます。

一つのsen_indexインスタンスを複数のスレッドで共有することができます。

一つの転置インデックスファイルを複数のプロセスで同時にopenすることができます。

排他制御なしに更新操作の実行と同時に参照操作を安全に実行することができます。
(ただしトランザクション隔離を実現しているわけではなく、未コミットのデータ
が参照される場合があります。)

複数のプロセスないしスレッドが一つのインデックスに対して同時に更新操作を実
行することはできません。(別途排他制御が必要になります)

 sen_index *sen_index_create(const char *path, int key_size, int flags, int initial_n_segments, sen_encoding encoding);

pathで与えられた新しい転置インデックスファイルを作成し、
対応するsen_indexインスタンスを返します。
失敗した場合はNULLを返します。

key_sizeに文書ID長(バイト長)を与えます。
key_sizeに0が指定された場合は可変長(nul終端する文字列)が指定されたとみなされます。

flagsには、以下のflagを組み合わせて指定します。

: SEN_INDEX_NORMALIZE : 英文字の大文字/小文字、全角文字/半角文字を正規化してインデックスに登録する
: SEN_INDEX_SPLIT_ALPHA : 英文字列を文字要素に分割する
: SEN_INDEX_SPLIT_DIGIT : 数字文字列を文字要素に分割する
: SEN_INDEX_SPLIT_SYMBOL : 記号文字列を文字要素に分割する
: SEN_INDEX_NGRAM : (形態素解析ではなく)n-gramを用いる
: SEN_INDEX_DELIMITED : (形態素解析ではなく)空白区切りで単語を区切る

initial_n_segmentsは、初期バッファサイズを与えます。
initial_n_segments * 256Kbytes分の容量が初期インデックスとして確保されます。
この数値が(実メモリサイズを越えない範囲で)大きいほど更新処理が高速になります。

encodingには、sen_enc_default, sen_enc_none, sen_enc_euc_jp,
sen_enc_utf8, sen_enc_sjis のいずれかを指定します。

 sen_index *sen_index_open(const char *path);

pathで与えられた既に作成済の転置インデックスファイルを開き、
対応するsen_indexインスタンスを返します。
失敗した場合はNULLを返します。

 sen_rc sen_index_close(sen_index *index);

indexに対応する転置インデックスファイルを閉じ、
sen_indexインスタンスを解放します。
成功すれば sen_success が、失敗すればエラーコードが返ります。

 sen_rc sen_index_remove(const char *path);

pathで与えられた転置インデックスファイルを削除します。
成功すれば sen_success が、失敗すればエラーコードが返ります。

 sen_rc sen_index_rename(const char *old_name, const char *new_name);

old_nameで与えられた転置インデックスファイルのファイル名を、
new_nameに変更します。
成功すれば sen_success が、失敗すればエラーコードが返ります。

 sen_rc sen_index_upd(sen_index *index, const void *key, const char *oldvalue, const char *newvalue);

index内のkeyに対応する文書の値をoldvalueからnewvalueに更新します。

新規文書である場合はoldvalueにNULLを指定します。

文書を削除する場合はnewvalueにNULLを指定します。

oldvalueには前回indexに登録した時の値を正しく指定する必要があります。

 sen_records *sen_index_sel(sen_index *index, const char *string);

indexから値にstringを含む文書を取り出し、sen_recordsインスタンスとし
て返します。

** sen_records 型

検索結果として返されるレコードの集合をメモリ上に一時的に格納するためのデータ型です。

レコード集合の内の一つのレコードをカレントレコードとして参照しています。

 int sen_records_next(sen_records *r, void *keybuf, int bufsize, int *score);

可能であればカレントレコードを一つ進めます。
成功した場合はカレントレコードのkey長を、失敗した場合は0を返します。
成功した場合は、
keybufが指定され、bufsizeがkey長以上であれば、
カレントレコードのkeyををkeybufにコピーし、
scoreにNULL以外の値が指定された場合はカレントレコードのスコアを*scoreにセットします。

 sen_rc sen_records_rewind(sen_records *records);

カレントレコードをクリアします。sen_records_rewind()実行後に
sen_records_next()を実行すれば、
最初のレコードから順番にレコードを読み出すことができます。

 int sen_records_curr_score(sen_records *records);

カレントレコードのスコア(検索クエリーに対する適合度)を返します。

 int sen_records_curr_key(sen_records *records, void *keybuf, int bufsize);

カレントレコードのkey長を返します。
カレントレコードが存在しない場合は0を返します。

sen_index_sel(), sen_index_select(), sen_records_rewind()実行直後は
カレントレコードは存在しません。sen_records_nextを実行する必要があります。

recordsオブジェクトに該当するindexのkey_sizeが0以外であれば、
カレントレコードが存在する場合の戻り値は常にkey_sizeと一致します。

keybufにNULL以外の値が渡され、bufsizeがカレントレコードのkey長以上であれば、
keybufにカレントレコードのkeyがコピーされます。

 int sen_records_nhits(sen_records *records);

recordsに含まれるレコードの数を返します。

 int sen_records_find(sen_records *records, const void *key);

recordsにkeyに対応するレコードが含まれているかどうかを調べます。
該当するレコードが存在すれば、そのレコードのスコアを返します。

 sen_rc sen_records_close(sen_records *records);

recordsインスタンスを解放します。

* advanced API

検索精度の精度の細かい制御を行うために advanced API を使用します。
advanced APIではsen_index型とsen_records型に加えて、インデックスに
登録する文書情報を格納するsen_values型を使用します。

** sen_values 型

sen_values型は、インデックスに登録する文書の内容をメモリ上に一時的に格納するためのデータ型です。
basic APIでは、文書の値はフラットな単一の文字列として扱いますが、advanced APIでは、一つの文書を複数の段落の集合として扱うことができます。また、それぞれの段落は、異なる重みを持つ文字列のリストとして管理できます。重みとは、文書内でその文字列が強調されている度合を示す整数値で、ある検索ワードに対して、重みの大きく設定された部分の文字列にマッチした文書の方がより適合度が高いものとみなして順位付けを行うことができます。

 sen_values *sen_values_open(void);

新たなsen_valuesインスタンスを生成します。

 sen_rc sen_values_close(sen_values *values);

sen_valuesインスタンスを解放します。

 sen_rc sen_values_add(sen_values *values, const char *str, unsigned int weight);

valuesに重み値weightを持つ文字列strを追加します。

** sen_records 型

advance APIでは、sen_records に対するより複雑な操作関数が提供されます。

 sen_records *sen_records_open(sen_rec_unit record_unit, sen_rec_unit subrec_unit, unsigned int max_n_subrecs);

新しい空のrecordsインスタンスを生成します。basic APIでは検索結果は文書毎でしたが、advanced APIではrecord_unitを指定することによってレコードの単位を指定できます。また、レコード毎に、その下位の単位で有限個のサブレコードを格納することができます。サブレコードの単位は、subrec_unitで指定します。
record_unit, subrec_unitは以下のいずれかを指定します。

: sen_rec_document : 文書単位
: sen_rec_section : 段落単位
: sen_rec_position : 出現位置単位
: sen_rec_userdef : ユーザ定義値単位(group化するときのみ有効です)
: sen_rec_none : サブレコードを格納しないことを指示します

max_n_subrecsは、レコード毎に格納するサブレコードの最大数を指定します。

 sen_records *sen_records_union(sen_records *a, sen_records *b);

records aとrecords bの和集合であるrecordsを返します。aとbは破壊されます。
aとbは同一のシンボル表を文書IDとするインデックスの検索結果であり、
record_unitが同一でなければなりません。

 sen_records *sen_records_subtract(sen_records *a, sen_records *b);

records aとrecords bの差集合であるrecordsを返します。aとbは破壊されます。
aとbは同一のシンボル表を文書IDとするインデックスの検索結果であり、
record_unitが同一でなければなりません。

 sen_records *sen_records_intersect(sen_records *a, sen_records *b);

records aとrecords bの共通集合であるrecordsを返します。aとbは破壊されます。
aとbは同一のシンボル表を文書IDとするインデックスの検索結果であり、
record_unitが同一でなければなりません。

 int sen_records_difference(sen_records *a, sen_records *b);

records aとrecords bから共通に含まれるレコードを取り除きます。共通に含まれていたレコードの数を返します。
aとbは同一のシンボル表を文書IDとするインデックスの検索結果であり、
record_unitが同一でなければなりません。

 sen_rc sen_records_sort(sen_records *records, int limit, sen_sort_optarg *optarg);

records内のレコードをソートし、上位limit個の要素をsen_records_next()で順次取り出せるようにします。
optargを指定することにより、ソートの方法を操作できます。sen_sort_optargの構造を以下に示します。

 struct _sen_sort_optarg {
   sen_sort_mode mode;
   int (*compar)(sen_records *, sen_recordh *, sen_recordh *, void *);
   void *compar_arg;
 };

modeには以下のいずれかを指定します。

: sen_sort_descending : 降順
: sen_sort_ascending : 昇順

コールバック関数comparは、第一引数にsen_records_sort()に指定されたrecordsが、
第二、第三引数に比較対象となる二つのレコードハンドルが、
第四引数にcompar_argが渡されます。比較関数は、第二の引数が第三の引数に対して、 1)小さい、2)等しい、3)大きいならば、 1)ゼロ未満、2)ゼロ、3)ゼロより大きい整数のいずれかを返さなければ なりません。二つの要素が等しいとき、並べ替えたrecordsにおける、二つの順序は未定義です。

comparにNULLが指定された場合は、各レコードのスコア値によってソートします。

optargにNULLが指定された場合は、modeにsen_sort_descendingが、comparにNULLが指定されたものとみなします。

 sen_rc sen_records_group(sen_records *records, int limit, sen_group_optarg *optarg);

recordsのrecord_unitをより大きな粒度の大きな単位に変更します。新たなrecord_unitの値が同一である複数のレコードは一つにまとめられ、サブレコードとして格納されます。limitには新たなレコード毎のサブレコードの最大値を指定します。
optargを指定することにより、グループ化の方法を操作できます。sen_group_optargの構造を以下に示します。

 struct _sen_group_optarg {
   sen_sort_mode mode;
   int (*func)(sen_records *, const sen_recordh *, void **, void *);
   void *func_arg;
   int key_size;
 };

modeは、limit個以上ののサブレコードが存在する場合に、保存対象とするサブレコードを選び出す順序を指定します。

コールバック関数funcを指定することによって、文書単位・段落単位・出現位置単位のいずれでもなく、ユーザの定義するグループ化キー単位でレコードをまとめることができます。funcは、第一引数にsen_records_group()に指定されたrecordsが、第二引数にレコードハンドルが、第三引数にグループ化のキーを格納するバッファが、第四引数にfunc_argが渡されます。funcの戻り値が0以外であれば、当該レコードは捨てられます。funcはレコードの内容に基づいてkey_sizeバイトのグループ化キーを算出し、バッファに格納しなければなりません。

 const sen_recordh * sen_records_curr_rec(sen_records *r);

カレントレコードのレコードハンドルを返します。

 const sen_recordh *sen_records_at(sen_records *records, const void *key, unsigned section, unsigned pos, int *score, int *n_subrecs);

recordsの中から、文書IDがkeyで段落番号がsectionで出現位置がposであるレコードを検索し、そのレコードハンドルを返します。score, n_subrecsが指定された場合は、該当するレコードのスコア、サブレコード数を返します。

 sen_rc sen_record_info(sen_records *r, const sen_recordh *rh,
		        void *keybuf, int bufsize, int *keysize,
		        int *section, int *pos, int *score, int *n_subrecs);

records中のレコードrhに該当する属性情報を取り出し、
keybufが指定され、bufsizeがkey長以上であればkeybufにkeyをコピーし、
section, pos, score, n_subrecsが指定されていれば、
セクション番号、位置、スコア、サブレコード数をそれぞれセットします。

 sen_rc sen_record_subrec_info(sen_records *r, const sen_recordh *rh, int index,
			       void *keybuf, int bufsize, int *keysize,
			       int *section, int *pos, int *score);

records中のレコードrhの、index番目のサブレコードの属性情報を取り出し、
keybufが指定され、bufsizeがkey長以上であればkeybufにkeyをコピーし、
section, pos, scoreが指定されていれば、
セクション番号、位置、スコアをそれぞれセットします。

** sen_index 型

advance APIでは、sen_index に対するより複雑な操作関数が提供されます。

 sen_index *sen_index_create_with_keys(const char *path, sen_sym *keys,
			     int flags, int initial_n_segments, sen_encoding encoding);

sen_index_createと同様にpathで与えられた新しい転置インデックスファイルを作成し、対応するsen_indexインスタンスを返しますが、文書IDを管理するシンボル表keysに既存のsen_symインスタンスを指定することができます。

 sen_index *sen_index_open_with_keys(const char *path, sen_sym *keys);

sen_index_openと同様にpathで与えられた既に作成済の転置インデックスファイルを開き、対応するsen_indexインスタンスを返しますが、文書IDを管理するシンボル表keysに既存のsen_symインスタンスを指定することができます。

 sen_rc sen_index_update(sen_index *index, const void *key, unsigned int section, sen_values *oldvalue, sen_values *newvalue);

keyに該当する文書のsection番目の段落の内容をoldvalueからnewvalueに更新します。

 sen_rc sen_index_select(sen_index *index, const char *string, sen_records *records, sen_sel_operator op, sen_select_optarg *optarg);

indexからstringにマッチする文書を検索し、演算子opに従ってrecordsに結果を反映します。
演算子opは以下のいずれかを指定します。

: sen_sel_or : stringにマッチするレコードをrecordsに追加します。
: sen_sel_and : stringにマッチしないレコードをrecordsから削除します。
: sen_sel_but : stringにマッチするレコードをrecordsから削除します。
: sen_sel_adjust : stringにマッチするレコードがrecordsに元々含まれていた場合にそのスコア値を加算します。

また、optargを指定することにより、indexからstringにマッチするレコードを検索する動作を制御できます。sen_select_optargの構造を以下に示します。

 struct _sen_select_optarg {
   sen_sel_mode mode;
   int similarity_threshold;
   int max_interval;
   int *weight_vector;
   int vector_size;
   int (*func)(sen_records *, const void *, int, void *);
   void *func_arg;
 };

modeには以下のいずれかを指定します。

: sen_sel_exact : stringが語境界と一致して現れるレコードのみを検索します
: sen_sel_partial : stringが語の列の一部と部分一致するレコードを検索します
: sen_sel_unsplit : stringをわかち書きせずに語の一部に一致するレコードを検索します
: sen_sel_near : stringをわかち書きした各語がmax_intervalの範囲内に現れるレコードを検索します
: sen_sel_similar : stringをわかち書きした語のうち、idf値が大きなsimilarity_threshold個の語のいずれかを含むレコードを検索します。

optargにNULLが指定された場合は、sen_sel_exactが指定されたとみなされます。

文書が複数の段落から構成される場合、特定の段落だけを検索対象としたり、スコアを持ち上げたりするために、weight_vectorを用います。weight_vectorにintの配列を指定し、配列の大きさをvector_sizeに指定すると、stringが現れた段落(1ベース)に対応する配列の要素の値をスコア値に乗算します。値が0であった場合は、対応する段落は検索対象から除外されます。

文書によって段落毎のweightが異なる場合には、コールバック関数funcを指定します。
stringにマッチするレコードが見つかる度に、records, 文書ID, 段落番号, func_argを
引数としてコールバック関数funcが呼び出され、その戻り値をweightとしてスコア値を算出します。

 sen_rc sen_index_info(sen_index *index, int *key_size, int *flags, int *initial_n_segments, sen_encoding *encoding);

indexがcreateされた時に指定されたkey_size, flags, initial_n_segments,
encodingの値を取得し、それぞれの引数の参照するアドレスに格納します。
第二、第三、第四、第五引数にNULLが指定された場合は、その引数は無視し、値を格納しません。

 sen_set * sen_index_related_terms(sen_index *index, const char *string,	const char *(*fetcher)(void *, void *), void *fetcher_arg);

stringに指定された文字列と関連する単語を抽出し、index->lexiconのidをキーとするsen_setオブジェクトに格納して返します。fetcherは、第一引数にindexのキー、第二引数にfetcher_argを指定して呼ばれると、文書の内容を文字列として返す関数を指定しなければなりません。

** sen_query

sen_queryは、さまざまな書式で指定された検索クエリを格納するデータ型です。

 sen_query *sen_query_open(const char *str, sen_sel_operator default_op,
                           int max_exprs, sen_encoding encoding);

新たなsen_queryインスタンスを生成します。
strに書式付きクエリ文字列を指定します。

default_opに、
演算子の既定値(演算子を省略した場合にどの演算を行うか)を指定します。
以下のいずれかの値を指定します。

: sen_sel_or : 演算子の規定値を'or'とします（デフォルト）
: sen_sel_and : 演算子の規定値を'and'とします（通常の検索エンジンでの検索クエリと同じ使用感です）
: sen_sel_but : 演算子の規定値を'-'とします
: sen_sel_adjust : 演算子の規定値を'>'とします

max_exprsに、検索クエリに指定する式の最大値を指定します。

encodingに、検索クエリの文字コードを、
sen_enc_default, sen_enc_none, sen_enc_euc_jp,
sen_enc_utf8, sen_enc_sjis のいずれかで指定します。

 const char *sen_query_rest(sen_query *q);

sen_query_open呼び出し後に、長すぎて受け付けられない部分の検索クエリを返します。

 sen_rc sen_query_exec(sen_index *i, sen_query *q, sen_records *r, sen_sel_operator op);

指定したsen_indexに対して、sen_queryの条件で検索を行い、結果を指定のsen_recordsに反映します。

演算子opは以下のいずれかを指定します。

: sen_sel_or : 条件にマッチするレコードをrに追加します。
: sen_sel_and : 条件にマッチしないレコードをrから削除します。
: sen_sel_but : 条件にマッチするレコードをrから削除します。
: sen_sel_adjust : 条件にマッチするレコードがrに元々含まれていた場合にそのスコア値を加算します。

** sen_index
 sen_rc sen_index_del(sen_index *i, const void *key);

指定したsen_indexのkeyに対応する文書に削除フラグを立て、検索対象から外します。
通常はsen_index_updを用いて削除を行ってください。

* low-level API

low-level APIを用いることによってSennaの内部のデータ構造にアクセスし、さらに複雑なデータの操作や検索処理が実現できます。
low-level APIでは、永続的なシンボル表を

** sen_set

キーと値のペアからなるレコードの集合をメモリ上で高速に操作するためのデータ型です。
検索結果の集合や、語彙の集合を操作するのに使用します。(sen_records型はsen_setから派生したデータ型です)
sen_setはキーが重複した複数のレコードを格納することはできません。

 sen_set *sen_set_open(unsigned key_size, unsigned value_size, unsigned index_size);

新たなsen_setインスタンスを生成します。
key_sizeにキー長、value_sizeに値の長さを指定します。
index_sizeには初期状態でのバッファのサイズを指定します。
key_sizeに0が指定された場合は可変長(nul終端する文字列)が指定されたとみなされます。
value_sizeに0が指定された場合は、値を格納する領域を確保しません。

 sen_rc sen_set_close(sen_set *set);

sen_setインスタンスを解放します。

 sen_rc sen_set_info(sen_set *set, unsigned *key_size, unsigned *value_size, unsigned *n_entries);

setインスタンスを生成した時に指定したkey_size, value_size、および格納されているレコードの数を取得します。第二、第三、第四引数にNULLが指定された場合は、その引数は無視し、値を格納しません。

 sen_set_eh *sen_set_get(sen_set *set, const void *key, void **value);

setに、keyに該当するレコードを登録し、レコードへのハンドルを返します。
valueにはレコードの値部分に該当するポインタを返されますので、
これを介して値を参照/更新できます。

 sen_set_eh *sen_set_at(sen_set *set, const void *key, void **value);

setから、keyに該当するレコードを検索し、レコードへのハンドルを返します。
該当するキーが存在しない場合はNULLを返します。
valueにはレコードの値部分に該当するポインタを返されますので、
これを介して値を参照/更新できます。

 sen_rc sen_set_del(sen_set *set, sen_set_eh *eh);

ehに指定したレコードハンドルに該当するレコードをsetから削除します。

 sen_set_cursor *sen_set_cursor_open(sen_set *set);

setに登録されているレコードを順番に取り出すためのカーソルを生成します。

 sen_set_eh *sen_set_cursor_next(sen_set_cursor *cursor, void **key, void **value);

cursorに従ってsetから次のレコードを取り出し、レコードへのハンドルを返します。
第二、第三引数にNULL以外のポインタを渡すと、keyにはレコードのキー部分に該当するポインタがvalueにはレコードの値部分に該当するポインタが返されます。

 sen_rc sen_set_cursor_close(sen_set_cursor *cursor);

cursorインスタンスを解放します。

 sen_rc sen_set_element_info(sen_set *set, const sen_set_eh *eh, void **key, void **value);

setに含まれるレコードハンドルehに対応するレコードの、キーへのポインタをkeyに、値へのポインタをvalueにセットします。第三、第四引数にNULLが指定された場合は、その引数は無視し、値を格納しません。

 sen_set *sen_set_union(sen_set *a, sen_set *b);

2つのsetの和集合となるsetを返します。この関数呼出によってa, bは解放されます。
キーが同一のレコードがa, bの両方に含まれていた場合は、aに含まれていたレコードの
値が引き継がれます。

 sen_set *sen_set_subtract(sen_set *a, sen_set *b);

2つのsetの差集合となるsetを返します。この関数呼出によってa, bは解放されます。

 sen_set *sen_set_intersect(sen_set *a, sen_set *b);

2つのsetの両方に同一のキーが存在するレコードからなるsetを返します。
この関数呼出によってa, bは解放されます。
返り値のsetのレコードの値には、aに含まれていたレコードの値が引き継がれます。

 int sen_set_difference(sen_set *a, sen_set *b);

set aとset bから共通に含まれるレコードを取り除きます。共通に含まれていたレコードの数を返します。

 sen_set_eh *sen_set_sort(sen_set *set, int limit, sen_set_sort_optarg *optarg);

set内のレコードをソートし、上位limit個のレコードハンドルの配列を返します。
optargを指定することにより、ソートの方法を操作できます。sen_sort_optargの構造を以下に示します。戻り値の配列は呼び出し側でfreeによって解放しなければなりません。

 struct _sen_set_sort_optarg {
   sen_sort_mode mode;
   int (*compar)(sen_set *, sen_set_eh *, sen_set_eh *, void *);
   void *compar_arg;
   sen_set *compar_arg0;
 };

コールバック関数comparは、第一引数にcompar_arg0が、
第二、第三引数に比較対象となる二つのレコードハンドルが、
第四引数にcompar_argが渡されます。比較関数は、第二の引数が第三の引数に対して、 1)小さい、2)等しい、3)大きいならば、 1)ゼロ未満、2)ゼロ、3)ゼロより大きい整数のいずれかを返さなければ なりません。二つの要素が等しいとき、並べ替えた結果における、二つの順序は未定義です。

comparにNULLが指定された場合には、レコードの値の先頭4byteをuint32とみなし、降順にソートします。

compar_arg0にNULLが指定された場合には、sen_set_sort()の第一引数に指定されたsetが代わりにcomparに渡されます。

optargにNULLが指定された場合には、modeにsen_sort_descendingが、comparにNULLが指定されたものとみなします。

** sen_sym

固定長のバイナリデータかnulで終端する可変長の文字列に一意な番号を割り当てるシンボル表ファイルに対応するデータ型です。
sen_symのインスタンスはファイルシステム上の特定のファイルに対応しており、格納された文書は永続的に保存されます。

なおsen_indexインスタンスは2つのsym_symインスタンスを含んでいます。

: keys : 文書IDとレコードIDとを対応付ける
: lexicon : 文書の内容を分かち書きした語彙と語彙IDとを対応付ける

 sen_sym * sen_sym_create(const char *path, unsigned key_size, unsigned flags, sen_encoding encoding);

pathで与えられた新しいシンボル表ファイルを作成し、対応するsen_symインスタンスを返します。失敗した場合はNULLを返します。

key_sizeにキー長(バイト長)を与えます。key_sizeに0が指定された場合は可変長(nul終端する文字列)が指定されたとみなされます。

flagsに SEN_SYM_WITH_SIS を指定した場合は、登録されたキーに対する後方一致検索が
可能になります。

encodingには、sen_enc_default, sen_enc_none, sen_enc_euc_jp,
sen_enc_utf8, sen_enc_sjis のいずれかを指定します。

 sen_sym * sen_sym_open(const char *path);

pathで与えられた既に作成済のシンボル表ファイルを開き、対応するsen_symインスタンスを返します。失敗した場合はNULLを返します。

 sen_rc sen_sym_info(sen_sym *sym, int *key_size, unsigned *flags, sen_encoding *encoding, unsigned *nrecords);

symインスタンスを生成した時に指定したkey_size, flags, encoding、および格納されているレコードの数を取得します。第二、第三、第四、第五引数にNULLが指定された場合は、その引数は無視し、値を格納しません。

 sen_rc sen_sym_close(sen_sym *sym);

symに対応するシンボル表ファイルを閉じ、sen_symインスタンスを解放します。
成功すれば sen_success が、失敗すればエラーコードが返ります。

 sen_rc sen_sym_remove(const char *path);

pathで与えられたシンボル表ファイルを削除します。成功すれば sen_success が、失敗すればエラーコードが返ります。

 sen_id sen_sym_get(sen_sym *sym, const unsigned char *key);

シンボル表symにkeyを登録し、対応するIDを返します。

 sen_id sen_sym_at(sen_sym *sym, const unsigned char *key);

シンボル表symからkeyに対応するIDを返します。未登録であった場合は SEN_SYM_NIL を返します。

 sen_rc sen_sym_del(sen_sym *sym, const unsigned char *key);

シンボル表symからkeyを削除します。

 unsigned int sen_sym_size(sen_sym *sym);

シンボル表symに含まれるキーの数を返します。

 int sen_sym_key(sen_sym *sym, sen_id id, unsigned char *keybuf, int bufsize);

シンボル表symからIDに対応するキーを返します。
対応するキーが見つかった場合はkey長を返します。
見つからない場合は0を返します。
対応するキーの検索に成功し、
またkeybufが指定され、bufsizeの長さkey長以上であった場合は、
keybufに該当するkeyをコピーして返します。

 sen_set * sen_sym_prefix_search(sen_sym *sym, const unsigned char *key);

keyに前方一致する全てのエントリを抽出し、それらのIDをキーとするsen_setインスタンスを返します。

 sen_set * sen_sym_suffix_search(sen_sym *sym, const unsigned char *key);

keyに後方一致する全てのエントリを抽出し、それらのIDをキーとするsen_setインスタンスを返します。(sym作成時にSEN_SYM_WITH_SISを指定した場合のみ有効です)

 sen_id sen_sym_common_prefix_search(sen_sym *sym, const unsigned char *key);

keyとキー文字列が最も長く前方一致するエントリを検索し、そのIDを返します。

 int sen_sym_pocket_get(sen_sym *sym, sen_id id);

sen_symの指定IDのエントリに格納された情報を取り出します。

 sen_rc sen_sym_pocket_set(sen_sym *sym, sen_id id, unsigned int value);

sen_symの指定IDのエントリにvalueを格納します。

 sen_id sen_sym_next(sen_sym *sym, sen_id id);

sen_symの指定IDの次のエントリのIDを返します。

* snippet API

snippet(KWIC)を作成するためのAPI。

 sen_snip *sen_snip_open(sen_encoding encoding, int flags, size_t width, unsigned int max_results,
                         const char *defaultopentag, const char *defaultclosetag,
                         sen_snip_mapping *mapping);

新たなsen_snipインスタンスを生成します。

encodingには、sen_enc_default, sen_enc_none, sen_enc_euc_jp, sen_enc_utf8, sen_enc_sjis のいずれかを指定します。

flagsには、SEN_SNIP_NORMALIZE(正規化して検索を行う)が指定できます。

widthは、snippetの幅をバイト長で指定します。eucやsjisの場合にはその半分、utf-8の場合にはその1/3の長さの日本語が格納できるでしょう。

max_resultsは、snippetの個数を指定します。

defaultopentagは、snippet中の検索単語の前につける文字列を指定します。

defaultclosetagは、snippet中の検索単語の後につける文字列を指定します。

mappingは、(現在は)NULLか-1を指定してください。-1を指定すると、HTMLのメタ文字列をエンコードしたsnippetを出力します。

''defaultopentag,defaultclosetagの指す内容は、sen_snip_closeを呼ぶまで変更しないでください。''

 sen_rc sen_snip_close(sen_snip *snip);

sen_snipインスタンスを破棄します。

 sen_rc sen_snip_add_cond(sen_snip *snip, const char *keyword,
                          const char *opentag, const char *closetag);

検索対象の単語と、その単語の前後に付与する文字列を指定します。

snipには、sen_snip_openで生成したsen_snipインスタンスを指定します。

keywordは、検索対象の単語を指定します。

opentagは、snippet中の検索単語の前につける文字列を指定します。
NULLを指定した場合には、sen_snip_openで指定したdefaultopentagが使用されます。

closetagは、snippet中の検索単語の後につける文字列を指定します。
NULLを指定した場合には、sen_snip_openで指定したdefaultclosetagが使用されます。

''opentag,closetagの指す内容は、sen_snip_closeを呼ぶまで変更しないでください。''

 sen_rc sen_snip_exec(sen_snip *snip, const char *string, unsigned int *nresults,
                      size_t *max_tagged_len);

検索対象の単語を検索し、snippetを生成します。

snipには、sen_snip_openで生成したsen_snipインスタンスを指定します。

stringには、snippetを生成する対象の文字列を指定します。

nresultsには、snippetを実際に生成できた個数が格納されます。

max_tagged_lenには、生成されたsnippetのうち、一番長いsnippetのナル文字を含めた長さが格納されます。

 sen_rc sen_snip_get_result(sen_snip *snip, const unsigned int index, char *result);

sen_snip_execで生成したsnippetを取り出します。

indexは、snippetの0からはじまるインデックスを指定します。

resultには、snippetの文字列が格納されます。
