まず, 初めに libwam の使用方法をざっと見ておきます.
まず, ヘッダファイルです. これは, geta/wam.hをインクルードすれば必要なものはだいたい入っているはずです. GETA のヘッダファイルは$GETAROOT/includeにあるので, コンパイラにその場所を教えるのも忘れてはなりません. その方法については後で説明します.
#include <geta/wam.h>
WAM を使うには, 最初に wam_init(3) を呼びだして (プロセスごとに)初期化を行う必要があります. wam_init(3) への引き数には$GETAROOTの絶対パスを渡すのですが, NULLを渡すと環境変数GETAROOTの値が用いられるので, 大抵の場合NULLを渡しておけば十分です.
wam_init(NULL);
次に wam_open により取り扱いたい WAM をオープンします. wam_open(3) の第1引き数にはハンドル(ショートネームも可)を渡します. 第2引き数には 0 を渡します. wam_open(3) は指定された WAM の取り扱うための資源を確保し, その WAM に関連付けられた識別子(*9)を返します. 以後, この WAM にアクセスするためにはこの識別子を用います.
WAM *w; w = wam_open("my-inbox", 0);
WAM を使い終わったら wam_close(3) により資源を開放しておきます. なお, wam_close を呼ばなくてもプロセスが終了した場合, この資源は自動的に開放されます.
wam_close(w);
行(列)の name と ID の相互変換は, wam_name2id(3) と wam_id2name(3) により行えます. ID はsymbol_t型であることに注意して下さい. 第1引き数は WAM の識別子です. また, 行と列のどちらの表を見たいのかも WAM に指示する必要があります. 行なら WAM_ROW, 列なら WAM_COL を第2引き数に渡します. これらの関数は失敗するとそれぞれ 0 と NULL ポインタを返します.
symbol_t id; char *name; name = "inbox/1"; if (!(id = wam_name2id(w, WAM_ROW, name))) { /* 行: name -> ID */ fprintf(stderr, "この name は登録されていません: [%s]\n", name); } id = 5; if (!(name = wam_id2name(w, WAM_COL, id))) { /* 列: ID -> name */ fprintf(stderr, "この ID は登録されていません: %d\n", id); }
次に, 行(列)の内容についてです. libwam では, 1行(列)の情報は struct xr_vec 型の変数にパックされています. elem_num は, その行に現れる値が 0 でない要素の数, freq_sum はその行の要素の値の和です. elems には値が 0 でない要素が ID の小さい順につまっています. すなわち, elems には elem_num 個の要素がつまっていることになります. 宣言では elems の要素数が 1 になっていますが, 0 .. elem_num-1 までなら安全にアクセスできます.
struct xr_vec { ival_t elem_num; /* # of elems */ ival_t freq_sum; /* sum of freq */ struct xr_elem elems[1]; };
各要素は struct xr_elem 型です. id がその要素の ID, freq がその要素の値です. symbol_t は符号無し 32 ビット整数, ival_t は符号付き 32 ビット整数です.
struct xr_elem { symbol_t id; /* network order */ ival_t freq; /* network order */ };また, ユーザの便宜を図るために以下の typedef がされています.
typedef struct xr_elem xr_elem; typedef struct xr_vec xr_vec;この構造体を取得するには wam_get_vec(3) を用います. これもやはりWAM の識別子に続いて WAM_ROW または WAM_ROL を渡します. それに続いて行(列)のID, 構造体へのポインタのポインタ, フラグを渡します. フラグに XR_HOSTORDER を渡すと 構造体に格納されているデータが普通に扱える形式に変換されます. wam_get_vec(3) の戻り値は値が 0 でない要素の数です (すなわち, 構造体の最初のメンバ, elem_num と同じ値になります. ). wam_get_vec(3) は失敗すると -1 を返します.
例えば WAM の"猿"という name が付いた列を取得するには次の様にします. (文字コードが, freqfile で使ったものと同じになるように注意して下さい. )
xr_vec *vec; int elem_num; if (!(id = wam_name2id(w, WAM_COL, "猿"))) { err(1, "失敗: 猿"); } if ((elem_num = wam_get_vec(w, WAM_COL, id, &vec, XR_HOSTORDER))==-1) { err(1, "失敗: get_vec"); } assert(elem_num == vec->elem_num); /* if XR_HOSTORDER */次の例は, 取得したベクタの要素を順に印刷しています. elems->id には xr_vec が行ベクタなら列の ID が, そうでなくて xr_vec が列ベクタなら行の ID が入っていますから, この場合はWAM_ROW で name に変換しなければなりません.
int i; for (i=0; i<elem_num; i++) { xr_elem *e = &vec->elems[i]; char *name; name = wam_id2name(w, WAM_ROW, e->id); printf("id=%d, name=%s, frq=%d\n", e->id, name, e->freq); }これで, 前の部分と合わせると, "猿"が現れる記事の name を全て印刷するプログラムの断片になります.
ここまでのサンプルを saru.c に保存し, コンパイル/リンクします. 先にも触れたように, コンパイラにヘッダファイルの位置を教えなければなりません. 必要なライブラリは libgetamu.a と libwam.a のふたつです. libgetamu.a は libwam.a で使用する雑関数が納められており, 必須です. これらは $GETAROOT/lib にあります. 従って, コマンドは以下の様になります. ライブラリを指定する順番も大切です(*10).
$ cc saru.c -I$GETAROOT/include -L$GETAROOT/lib -lwam -lgetamuこれでa.outができますから実行してみます.
$ ./a.out ...どうやら, うまく動いている様です.