/*! 
\file deque
dequeは可変長な両端キューである。
先頭と末尾での要素の挿入・削除の計算量がO(1)であり、それ以外の位置の要素の挿入・削除の計算量はO(N)である。
インデックスによる要素のランダムアクセスが可能。

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

\code
#include <cstl/deque.h>

#define CSTL_DEQUE_INTERFACE(Name, Type)
#define CSTL_DEQUE_IMPLEMENT(Name, Type)
\endcode

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

また、\b CSTL_DEQUE_INTERFACE() を展開する前に、<cstl/algorithm.h>をインクルードすることにより、
<a href="algorithm.html">アルゴリズム</a>が使用可能となる。

\par 使用例:
\include deque_example.c

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

 */

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

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


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

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

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

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

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

/*! 
 * \brief インデックスによる要素のアクセス
 * 
 * \param self dequeオブジェクト
 * \param idx インデックス
 *
 * \return \a self の\a idx 番目の要素へのポインタ
 *
 * \pre \a idx が\a self の要素数より小さい値であること。
 *
 * \attention 戻り値は\a self の変更により無効となる。
 */
T *Deque_at(Deque *self, size_t idx);

/*! 
 * \brief 最初の要素のアクセス
 * 
 * \param self dequeオブジェクト
 * 
 * \return \a self の最初の要素へのポインタ
 *
 * \pre \a self が空でないこと。
 *
 * \attention 戻り値は\a self の変更により無効となる。
 */
T *Deque_front(Deque *self);

/*! 
 * \brief 最後の要素のアクセス
 * 
 * \param self dequeオブジェクト
 * 
 * \return \a self の最後の要素へのポインタ
 *
 * \pre \a self が空でないこと。
 *
 * \attention 戻り値は\a self の変更により無効となる。
 */
T *Deque_back(Deque *self);

/*! 
 * \brief 要素を挿入
 *
 * \a self の\a idx 番目の位置に、\a data のコピーを挿入する。
 *
 * \param self dequeオブジェクト
 * \param idx 挿入する位置
 * \param data 挿入するデータ
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \pre \a idx が\a self の要素数以下の値であること。
 */
int Deque_insert(Deque *self, size_t idx, T data);

/*! 
 * \brief 複数個の要素を挿入
 *
 * \a self の\a idx 番目の位置に、\a data のコピーを\a n 個挿入する。
 * 
 * \param self dequeオブジェクト
 * \param idx 挿入する位置
 * \param n 挿入するデータの個数
 * \param data 挿入するデータ
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \pre \a idx が\a self の要素数以下の値であること。
 */
int Deque_insert_n(Deque *self, size_t idx, size_t n, T data);

/*! 
 * \brief 配列の要素を挿入
 * 
 * \a self の\a idx 番目の位置に、\a data という配列から\a n 個の要素のコピーを挿入する。
 * 
 * \param self dequeオブジェクト
 * \param idx 挿入する位置
 * \param data 挿入するデータの配列
 * \param n 挿入するデータの個数
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \pre \a idx が\a self の要素数以下の値であること。
 * \pre \a data がNULLでないこと。
 */
int Deque_insert_array(Deque *self, size_t idx, T const *data, size_t n);

/*! 
 * \brief 指定範囲の要素を挿入
 * 
 * \a self の\a idx 番目の位置に、\a x の\a xidx 番目から\a n 個の要素のコピーを挿入する。
 * \a self と\a x は同じオブジェクトでもよい。
 *
 * \param self dequeオブジェクト
 * \param idx 挿入する位置
 * \param x コピー元のdequeオブジェクト
 * \param xidx \a x のコピー開始インデックス
 * \param n コピーする要素数
 * 
 * \return 挿入に成功した場合、非0を返す。
 * \return メモリ不足の場合、\a self の変更を行わず0を返す。
 *
 * \pre \a xidx + \a n が\a x の要素数以下の値であること。
 * \pre \a idx が\a self の要素数以下の値であること。
 */
int Deque_insert_range(Deque *self, size_t idx, Deque *x, size_t xidx, size_t n);

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

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

/*! 
 * \brief 要素を削除
 * 
 * \a self の\a idx 番目から\a n 個の要素を削除する。
 * 
 * \param self dequeオブジェクト
 * \param idx 削除開始インデックス
 * \param n 削除する要素数
 * 
 * \pre \a idx + \a n が\a self の要素数以下の値であること。
 */
void Deque_erase(Deque *self, size_t idx, size_t n);

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

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

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

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

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


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