/*! 
\file map

mapはキーと値のペアを要素とするコンテナである。
要素を挿入すると、キーによって自動的にソートされる。同じキーの要素を2個以上挿入することはできない。
挿入した要素のキーは読み出し専用となる。
キーによる要素のランダムアクセスが可能。
要素の挿入・削除・キーの検索・キーによる要素のランダムアクセスの計算量はO(log N)である。

multimapはキーの重複が許されることと、キーによる要素のランダムアクセスが不可能であることを除き、mapと同じである。

map/multimapを使うには、<cstl/map.h>をインクルードし、以下のマクロを用いてコードを展開する必要がある。

\code
#include <cstl/map.h>

#define CSTL_MAP_INTERFACE(Name, KeyType, ValueType)
#define CSTL_MAP_IMPLEMENT(Name, KeyType, ValueType, Compare)

#define CSTL_MULTIMAP_INTERFACE(Name, KeyType, ValueType)
#define CSTL_MULTIMAP_IMPLEMENT(Name, KeyType, ValueType, Compare)
\endcode

\b CSTL_MAP_INTERFACE() は任意の名前と要素の型のmapのインターフェイスを展開する。
\b CSTL_MAP_IMPLEMENT() はその実装を展開する。

\b CSTL_MULTIMAP_INTERFACE() は任意の名前と要素の型のmultimapのインターフェイスを展開する。
\b CSTL_MULTIMAP_IMPLEMENT() はその実装を展開する。

\par 使用例:
\include map_example.c

\attention 以下に説明する型定義・関数は、
\b CSTL_MAP_INTERFACE(Name, KeyType, ValueType) , \b CSTL_MULTIMAP_INTERFACE(Name, KeyType, ValueType) 
の\a Name に\b Map , \a KeyType に\b KeyT , \a ValueType に\b ValueT を仮に指定した場合のものである。
実際に使用する際には、使用例のように適切な引数を指定すること。
\attention また、map専用/multimap専用と記した関数以外の関数は、map/multimap共通の関数である。

 */



/*! 
 * \brief map用インターフェイスマクロ
 *
 * 任意の名前と要素の型のmapのインターフェイスを展開する。
 *
 * \param Name 既存の型と重複しない任意の名前。mapの型名と関数のプレフィックスになる
 * \param KeyType 任意の要素のキーの型
 * \param ValueType 任意の要素の値の型
 * \attention 引数は CSTL_MAP_IMPLEMENT()の引数と同じものを指定すること。
 * \attention \a KeyType , \a ValueType に括弧を付けないこと。
 */
#define CSTL_MAP_INTERFACE(Name, KeyType, ValueType)

/*! 
 * \brief map用実装マクロ
 *
 * CSTL_MAP_INTERFACE()で展開したインターフェイスの実装を展開する。
 *
 * - \a KeyType が整数型、小数型、ポインタ型など、2つの値を演算子(==, <, >)で比較できる型の場合、
 *   要素のソートの順序を昇順にするならば CSTL_LESS を、降順にするならば CSTL_GREATER を\a Compare に指定する。
 *
 * - \a KeyType がその他の型の場合、
 *   \code
 *   int comp(KeyType x, KeyType y);
 *   \endcode
 *   のような引数と戻り値を持ち、
 *   x == yならば0を、x < yならば正または負の整数を、x > yならばx < yの場合と逆の符号の整数を
 *   返す比較関数またはマクロを\a Compare に指定する。
 *   尚、\a KeyType が文字列型(const char *)ならば、C標準関数のstrcmpが指定可能である。
 *
 * \param Name 既存の型と重複しない任意の名前。mapの型名と関数のプレフィックスになる
 * \param KeyType 任意の要素のキーの型
 * \param ValueType 任意の要素の値の型
 * \param Compare 要素のキーを比較する関数またはマクロ
 * \attention \a Compare 以外の引数は CSTL_MAP_INTERFACE()の引数と同じものを指定すること。
 * \attention \a KeyType , \a ValueType , \a Compare に括弧を付けないこと。
 */
#define CSTL_MAP_IMPLEMENT(Name, KeyType, ValueType, Compare)

/*! 
 * \brief multimap用インターフェイスマクロ
 *
 * 任意の名前と要素の型のmultimapのインターフェイスを展開する。
 *
 * 使用方法は CSTL_MAP_INTERFACE()と同じである。
 */
#define CSTL_MULTIMAP_INTERFACE(Name, KeyType, ValueType)

/*! 
 * \brief multimap用実装マクロ
 *
 * CSTL_MULTIMAP_INTERFACE()で展開したインターフェイスの実装を展開する。
 *
 * 使用方法は CSTL_MAP_IMPLEMENT()と同じである。
 */
#define CSTL_MULTIMAP_IMPLEMENT(Name, KeyType, ValueType, Compare)


/*! 
 * \brief 昇順指定
 * 
 * 要素を昇順にソートする場合、 CSTL_MAP_IMPLEMENT() , CSTL_MULTIMAP_INTERFACE() の \a Compare 引数に指定する。
 *
 * \param x 1つ目のキー
 * \param y 2つ目のキー
 * 
 * \retval 0 \a x == \a y の場合
 * \retval 負の値 \a x < \a y の場合
 * \retval 正の値 \a x > \a y の場合
 */
#define CSTL_LESS(x, y)		((x) == (y) ? 0 : (x) < (y) ? -1 : 1)

/*! 
 * \brief 降順指定
 * 
 * 要素を降順にソートする場合、 CSTL_MAP_IMPLEMENT() , CSTL_MULTIMAP_INTERFACE() の \a Compare 引数に指定する。
 *
 * \param x 1つ目のキー
 * \param y 2つ目のキー
 * 
 * \retval 0 \a x == \a y の場合
 * \retval 負の値 \a x > \a y の場合
 * \retval 正の値 \a x < \a y の場合
 */
#define CSTL_GREATER(x, y)	((x) == (y) ? 0 : (x) > (y) ? -1 : 1)


/*! 
 * \brief map/multimapの型
 *
 * 抽象データ型となっており、内部データメンバは非公開である。
 *
 * 以下、 Map_new() から返されたMap構造体へのポインタをmapオブジェクトという。
 */
typedef struct Map Map;

/*! 
 * \brief イテレータの型
 *
 * 要素の位置を示す。
 *
 * 以下、関数から返されたイテレータを有効なイテレータという。
 * 宣言されただけのイテレータ、または削除された要素のイテレータを無効なイテレータという。
 */
typedef struct MapRBTree *MapIterator;

/*! 
 * \brief 生成
 *
 * 要素数が0のmap/multimapを生成する。
 * 
 * \return 生成に成功した場合、mapオブジェクトを返す。
 * \return メモリ不足の場合、NULLを返す。
 */
Map *Map_new(void);

/*! 
 * \brief 破棄
 * 
 * \a self のすべての要素を削除し、\a self を破棄する。
 * \a self がNULLの場合、何もしない。
 *
 * \param self mapオブジェクト
 */
void Map_delete(Map *self);

/*! 
 * \brief 要素数を取得
 * 
 * \param self mapオブジェクト
 * 
 * \return \a self の要素数
 */
size_t Map_size(Map *self);

/*! 
 * \brief 空チェック
 * 
 * \param self mapオブジェクト
 * 
 * \return \a self の要素数が0の場合、非0を返す。
 * \return \a self の要素数が1以上の場合、0を返す。
 */
int Map_empty(Map *self);

/*! 
 * \brief 最初の要素のイテレータ
 * 
 * \param self mapオブジェクト
 * 
 * \return \a self の最初の要素のイテレータ
 */
MapIterator Map_begin(Map *self);

/*! 
 * \brief 最後の要素の次のイテレータ
 * 
 * \param self mapオブジェクト
 * 
 * \return \a self の最後の要素の次のイテレータ
 */
MapIterator Map_end(Map *self);

/*! 
 * \brief 最後の要素のイテレータ
 * 
 * \param self mapオブジェクト
 * 
 * \return \a self の最後の要素のイテレータ
 */
MapIterator Map_rbegin(Map *self);

/*! 
 * \brief 最初の要素の前のイテレータ
 * 
 * \param self mapオブジェクト
 * 
 * \return \a self の最初の要素の前のイテレータ
 */
MapIterator Map_rend(Map *self);

/*! 
 * \brief 次のイテレータ
 * 
 * \param pos イテレータ
 * 
 * \return \a pos が示す位置の要素の次のイテレータ
 *
 * \pre \a pos が有効なイテレータであること。
 * \pre \a pos が Map_end() または Map_rend() でないこと。
 */
MapIterator Map_next(MapIterator pos);

/*! 
 * \brief 前のイテレータ
 * 
 * \param pos イテレータ
 * 
 * \return \a pos が示す位置の要素の前のイテレータ
 *
 * \pre \a pos が有効なイテレータであること。
 * \pre \a pos が Map_end() または Map_rend() でないこと。
 */
MapIterator Map_prev(MapIterator pos);

/*! 
 * \brief イテレータによる要素のキーのアクセス
 * 
 * \param pos イテレータ
 * 
 * \return \a pos が示す位置の要素のキーへのポインタ
 *
 * \pre \a pos が有効なイテレータであること。
 * \pre \a pos が Map_end() または Map_rend() でないこと。
 *
 * \attention 戻り値のポインタの参照先はconstである。
 */
KeyT const *Map_key(MapIterator pos);

/*! 
 * \brief イテレータによる要素の値のアクセス
 * 
 * \param pos イテレータ
 * 
 * \return \a pos が示す位置の要素の値へのポインタ
 *
 * \pre \a pos が有効なイテレータであること。
 * \pre \a pos が Map_end() または Map_rend() でないこと。
 */
ValueT *Map_value(MapIterator pos);

/*! 
 * \brief キーによる要素のアクセス(map専用)
 * 
 * \param self mapオブジェクト
 * \param key キー
 *
 * \return \a self の\a key というキーの要素の値へのポインタを返す。
 * \return \a self が\a key というキーの要素を持っていない場合、\a key というキーの新しい要素(値は不定)を挿入し、その要素の値へのポインタを返す。
 * \return メモリ不足の場合、\a self の変更を行わずNULLを返す。
 *
 * \attention この関数はmapのみで提供される。
 * \attention メモリ不足の場合、NDEBUGマクロが未定義ならばアサーションに失敗する。
 */
ValueT *Map_at(Map *self, KeyT key);

/*! 
 * \brief 要素を挿入(map専用)
 *
 * \a key と\a value のコピーのペアを要素として\a self に挿入する。
 *
 * \param self mapオブジェクト
 * \param key 挿入する要素のキー
 * \param value 挿入する要素の値
 * \param success 成否を格納する変数へのポインタ。ただし、NULLを指定した場合はアクセスしない。
 * 
 * \return 挿入に成功した場合、*\a success に非0の値を格納し、新しい要素のイテレータを返す。
 * \return \a self が既に\a key というキーの要素を持っている場合、挿入を行わず、*\a success に0を格納し、その要素のイテレータを返す。
 * \return メモリ不足の場合、*\a success に0を格納し、\a self の変更を行わず0を返す。
 *
 * \attention この関数はmapのみで提供される。
 */
MapIterator Map_insert(Map *self, KeyT key, ValueT value, int *success);

/*! 
 * \brief 要素を挿入(multimap専用)
 *
 * \a key と\a value のコピーのペアを要素として\a self に挿入する。
 * \a self が既に\a key というキーの要素を持っている場合、そのキーの一番最後の位置に挿入される。
 *
 * \param self mapオブジェクト
 * \param key 挿入する要素のキー
 * \param value 挿入する要素の値
 * 
 * \return 挿入に成功した場合、新しい要素のイテレータを返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \attention この関数はmultimapのみで提供される。
 */
MapIterator Map_insert(Map *self, KeyT key, ValueT value);

/*! 
 * \brief 指定範囲の要素を挿入
 * 
 * [\a first, \a last)の範囲の要素のコピーを\a self に挿入する。
 * multimapの場合、[\a first, \a last)の要素は\a self が持つ要素でもよい。
 *
 * \param self mapオブジェクト
 * \param first コピー元の範囲の開始位置
 * \param last コピー元の範囲の終了位置
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \pre [\a first, \a last)が有効なイテレータであること。
 */
int Map_insert_range(Map *self, MapIterator first, MapIterator last);

/*! 
 * \brief 要素を削除
 * 
 * \a self の\a pos が示す位置の要素を削除する。
 * 
 * \param self mapオブジェクト
 * \param pos 削除する要素の位置
 * 
 * \return 削除した要素の次のイテレータ
 *
 * \pre \a pos が\a self の有効なイテレータであること。
 * \pre \a pos が Map_end() または Map_rend() でないこと。
 */
MapIterator Map_erase(Map *self, MapIterator pos);

/*! 
 * \brief 指定範囲の要素を削除
 * 
 * \a self の[\a first, \a last)の範囲の要素を削除する。
 * 
 * \param self mapオブジェクト
 * \param first 削除する範囲の開始位置
 * \param last 削除する範囲の終了位置
 * 
 * \return \a last
 *
 * \pre [\a first, \a last)が\a self の有効なイテレータであること。
 */
MapIterator Map_erase_range(Map *self, MapIterator first, MapIterator last);

/*! 
 * \brief 指定キーの要素を削除
 * 
 * \a self の\a key というキーの要素をすべて削除する。
 * 
 * \param self mapオブジェクト
 * \param key 削除する要素のキー
 * 
 * \return 削除した数
 */
size_t Map_erase_key(Map *self, KeyT key);

/*! 
 * \brief 全要素を削除
 *
 * \a self のすべての要素を削除する。
 * 
 * \param self mapオブジェクト
 */
void Map_clear(Map *self);

/*! 
 * \brief 交換
 *
 * \a self と\a x の内容を交換する。
 * 
 * \param self mapオブジェクト
 * \param x \a self と内容を交換するmapオブジェクト
 */
void Map_swap(Map *self, Map *x);

/*! 
 * \brief 指定キーの要素をカウント
 * 
 * \param self mapオブジェクト
 * \param key カウントする要素のキー
 * 
 * \return \a self の\a key というキーの要素の数
 */
size_t Map_count(Map *self, KeyT key);

/*! 
 * \brief 指定キーの要素を検索
 * 
 * \a self の\a key というキーの最初の要素を検索する。
 *
 * \param self mapオブジェクト
 * \param key 検索する要素のキー
 * 
 * \return 見つかった場合、その要素のイテレータを返す。
 * \return 見つからない場合、 Map_end(\a self) を返す。
 */
MapIterator Map_find(Map *self, KeyT key);

/*! 
 * \brief 最初の位置の検索
 * 
 * ソートの基準に従い、\a self の\a key \b 以上 のキーの最初の要素を検索する。
 *
 * \param self mapオブジェクト
 * \param key 検索する要素のキー
 * 
 * \return 見つかった場合、その要素のイテレータを返す。
 * \return 見つからない場合、 Map_end(\a self) を返す。
 */
MapIterator Map_lower_bound(Map *self, KeyT key);

/*! 
 * \brief 最後の位置の検索
 * 
 * ソートの基準に従い、\a self の\a key \b より大きい キーの最初の要素を検索する。
 *
 * \param self mapオブジェクト
 * \param key 検索する要素のキー
 * 
 * \return 見つかった場合、その要素のイテレータを返す。
 * \return 見つからない場合、 Map_end(\a self) を返す。
 */
MapIterator Map_upper_bound(Map *self, KeyT key);


/* vim:set ts=4 sts=4 sw=4 ft=c: */
