/*! 
\file list

listは双方向リンクリストである。
任意の位置での要素の挿入・削除の計算量がO(1)であるが、要素のランダムアクセスはできない。

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

\code
#include <cstl/list.h>

#define CSTL_LIST_INTERFACE(Name, Type)
#define CSTL_LIST_IMPLEMENT(Name, Type)
\endcode

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

\par 使用例:
\include list_example.c

\attention 以下に説明する型定義・関数は、
\b CSTL_LIST_INTERFACE(Name, Type) の\a Name に\b List , \a Type に\b T を仮に指定した場合のものである。
実際に使用する際には、使用例のように適切な引数を指定すること。

 */



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

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


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

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

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

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

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

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

/*! 
 * \brief 最初の要素のイテレータ
 * 
 * \param self listオブジェクト
 * 
 * \return \a self の最初の要素のイテレータ
 */
ListIterator List_begin(List *self);

/*! 
 * \brief 最後の要素の次のイテレータ
 * 
 * \param self listオブジェクト
 * 
 * \return \a self の最後の要素の次のイテレータ
 */
ListIterator List_end(List *self);

/*! 
 * \brief 最後の要素のイテレータ
 * 
 * \param self listオブジェクト
 * 
 * \return \a self の最後の要素のイテレータ
 */
ListIterator List_rbegin(List *self);

/*! 
 * \brief 最初の要素の前のイテレータ
 * 
 * \param self listオブジェクト
 * 
 * \return \a self の最初の要素の前のイテレータ
 */
ListIterator List_rend(List *self);

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

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

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

/*! 
 * \brief 最初の要素のアクセス
 * 
 * \param self listオブジェクト
 * 
 * \return \a self の最初の要素へのポインタ
 *
 * \pre \a self が空でないこと。
 */
T *List_front(List *self);

/*! 
 * \brief 最後の要素のアクセス
 * 
 * \param self listオブジェクト
 * 
 * \return \a self の最後の要素へのポインタ
 *
 * \pre \a self が空でないこと。
 */
T *List_back(List *self);

/*! 
 * \brief 要素を挿入
 *
 * \a self の\a pos が示す位置に、\a data のコピーを挿入する。
 *
 * \param self listオブジェクト
 * \param pos 挿入する位置
 * \param data 挿入するデータ
 * 
 * \return 挿入に成功した場合、新しい要素のイテレータを返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \pre \a pos が\a self の有効なイテレータであること。
 */
ListIterator List_insert(List *self, ListIterator pos, T data);

/*! 
 * \brief 複数個の要素を挿入
 *
 * \a self の\a pos が示す位置に、\a data のコピーを\a n 個挿入する。
 * 
 * \param self listオブジェクト
 * \param pos 挿入する位置
 * \param n 挿入するデータの個数
 * \param data 挿入するデータ
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \pre \a pos が\a self の有効なイテレータであること。
 */
int List_insert_n(List *self, ListIterator pos, size_t n, T data);

/*! 
 * \brief 配列の要素を挿入
 * 
 * \a self の\a pos が示す位置に、\a data という配列から\a n 個の要素のコピーを挿入する。
 * 
 * \param self listオブジェクト
 * \param pos 挿入する位置
 * \param data 挿入するデータの配列
 * \param n 挿入するデータの個数
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \pre \a pos が\a self の有効なイテレータであること。
 * \pre \a data がNULLでないこと。
 */
int List_insert_array(List *self, ListIterator pos, T const *data,
					  size_t n);

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

/*! 
 * \brief 先頭に要素を挿入
 * 
 * \a data のコピーを\a self の最初の要素として挿入する。
 *
 * \param self listオブジェクト
 * \param data 挿入するデータ
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 */
int List_push_front(List *self, T data);

/*! 
 * \brief 末尾に要素を挿入
 * 
 * \a data のコピーを\a self の最後の要素として挿入する。
 *
 * \param self listオブジェクト
 * \param data 挿入するデータ
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 */
int List_push_back(List *self, T data);

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

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

/*! 
 * \brief 最初の要素を削除
 * 
 * \a self の最初の要素を削除する。
 *
 * \param self listオブジェクト
 *
 * \pre \a self が空でないこと。
 */
void List_pop_front(List *self);

/*! 
 * \brief 最後の要素を削除
 * 
 * \a self の最後の要素を削除する。
 *
 * \param self listオブジェクト
 *
 * \pre \a self が空でないこと。
 */
void List_pop_back(List *self);

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

/*! 
 * \brief 要素数を変更
 *
 * \a self の要素数を\a n 個に変更する。
 * \a n が\a self の現在の要素数以下の場合、要素数が\a n 個になるまで末尾から要素が削除される。
 * \a n が\a self の現在の要素数より大きい場合、要素数が\a n 個になるまで\a data のコピーが末尾から挿入される。
 * 
 * \param self listオブジェクト
 * \param n 要素数
 * \param data 挿入するデータ
 * 
 * \return 要素数の変更に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 */
int List_resize(List *self, size_t n, T data);

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

/*! 
 * \brief つなぎ換え
 * 
 * \a self の\a pos が示す位置に、\a x の[\a first, \a last)の範囲の要素を移動する。
 * 
 * \param self listオブジェクト
 * \param pos つなぎ換え先
 * \param x [\a first, \a last)の要素を持つlistオブジェクト
 * \param first つなぎ換え元の範囲の開始位置
 * \param last つなぎ換え元の範囲の終了位置
 *
 * \pre \a pos が\a self の有効なイテレータであること。
 * \pre [\a first, \a last)が\a x の有効なイテレータであること。
 * \pre \a self と\a x が同一ならば\a pos は[\a first, \a last)の範囲外であること。
 */
void List_splice(List *self, ListIterator pos, List *x,
				 ListIterator first, ListIterator last);

/*! 
 * \brief ソート
 * 
 * \a self のすべての要素を比較関数\a comp に従ってソートする。
 * このソートは安定である。
 *
 * \param self listオブジェクト
 * \param comp 比較関数
 *
 * \pre \a comp には、*p1 == *p2ならば0を、*p1 < *p2ならば正または負の整数を、*p1 > *p2ならば*p1 < *p2の場合と逆の符号の整数を返す関数を指定すること。
 *      (C標準関数のqsort(), bsearch()に使用する関数ポインタと同じ仕様)
 */
void List_sort(List *self, int (*comp) (const void *p1, const void *p2));

/*! 
 * \brief 逆順に並べ替え
 * 
 * \a self のすべての要素を逆順に並べ替える。
 * 
 * \param self listオブジェクト
 */
void List_reverse(List *self);

/*! 
 * \brief マージ
 * 
 * ソートされた状態である\a self と\a x において、\a x のすべての要素を比較関数\a comp に従って\a self にマージする。
 * \a self はソートされた状態になり、\a x は空になる。
 * 
 * \param self listオブジェクト
 * \param x \a self にマージされるlistオブジェクト
 * \param comp 比較関数
 *
 * \pre \a comp には、*p1 == *p2ならば0を、*p1 < *p2ならば正または負の整数を、*p1 > *p2ならば*p1 < *p2の場合と逆の符号の整数を返す関数を指定すること。
 *      (C標準関数のqsort(), bsearch()に使用する関数ポインタと同じ仕様)
 * \pre selfとxがcompに従ってソートされていること。
 */
void List_merge(List *self, List *x,
				int (*comp) (const void *p1, const void p2*));


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