ヘッダだけで使えるCのコンテナライブラリ uthash
Cには標準のコンテナライブラリがありません。有名なOSSは自前の実装を抱えているようですが、小規模なプロダクトではそうはいかないので、何かしらのライブラリを利用するのが現実的です。
といっても、デファクトスタンダードのようなものが見当たらないので、とりあえずuthashを試してみました。GLibが有力かなとも考えたのですが、少しコンテナを使いたいだけなのに大げさすぎるかなというのと、uthashはヘッダファイルをインクルードするだけで使えるというのがあって、とりあえずuthashを選択しました。修正BSDライセンスで利用できるというのも、場合によってはポイントになるかなと思います。
この記事では、uthashの使い方を簡単に紹介します。uthashにはハッシュテーブルだけでなくリンクリスト (単方向/双方向/双方向循環)・動的配列・動的文字列も含まれていますが、今回はそれらには触れません。
使い方
インストール
ヘッダファイルだけで利用できるので、srcディレクトリにパスを通すなりコピーして自分のところに持ってくるなりすればOKです。
構造体の定義
uthashでは、構造体に管理用のハンドルを埋め込むことでその構造体を扱うことができるようになります。hhというメンバがそれです。hh以外の名前にすることも可能ですが、記述が増えて面倒なので、複数キーを扱うなどの目的以外ではオススメはしません。
keyは構造体のキーです。こちらは自由な名前を付けることができます。今回は文字列を構造体に埋め込んでいますが、整数・文字列のポインタ・ポインタ・構造体をキーにすることも可能です。
宣言
要素の追加
ただし、この時 “abc” というkeyの要素がハッシュテーブルに存在してはならず、そのことを保証するのは利用者の責任です。すでに要素が存在する場合にはその要素を取得し、存在しない場合だけ追加するのであれば以下のようにします。
要素の検索
イテレーション
ただし、これだと途中で要素を削除するとうまく動作しないため、ループ内でHASH_DELを利用する場合はHASH_ITERを利用します。
要素の削除
すべての要素を削除する場合はHASH_ITERと組み合わせます。
要素数のカウント
ハッシュテーブルを引数に取る関数
uthashはマクロで構築されているので分かりづらいのですが、tableの中身は機能の呼び出しによって変化しています。そのため、ハッシュテーブルを引数に取る関数を作る場合は、以下のように要素のポインタのポインタを受け取るようにし、新しい値が関数の呼び出し元に反映されるようにします。