
Namespace System
Namespace Collections
Namespace Generic

Interface IEnumerable<T>
	' Method
	Function GetEnumerator() As IEnumerator<T>
End Interface

Interface IEnumerator<T>
	' Methods
	Function MoveNext() As Boolean
	Sub Reset()
	' Property
	Function Current() As T
End Interface


Class ICollection<T>
	Implements IEnumerable<T>, IEnumerator<T>
Public
	' Property
	Abstract Function Count() As Long
	Abstract Function IsReadOnly() As Boolean

	' Methods
	Abstract Sub Add( item As T )
	Abstract Sub Clear()
'	Abstract Function Contains ( item As T ) As Boolean
'	Abstract Sub CopyTo (ByRef array As List<T>, arrayIndex As Long )
	Abstract Function Remove( item As T ) As Boolean
End Class


Class IList<T>
	Inherits ICollection<T>
Public
	' Property
	Abstract Sub Operator[] ( index As Long, item As T )
	Abstract Function Operator[] ( index As Long ) As T
	' Methods
'	Abstract Function Item ( index As Long ) As T
	Abstract Function IndexOf( item As T ) As Long
	Abstract Sub Insert( index As Long, item As T )
	Abstract Sub RemoveAt( index As Long )
End Class


Class List<T>
	Inherits IList<T>

	items As *T
	size As Long

	currentIndexForEnumerator As Long

	Sub Realloc( allocateSize As Long )
		items = realloc( items, allocateSize * SizeOf(T) )
	End Sub

Public
	Sub List()
		items = GC_malloc( 1 )

		' 列挙子の位置を初期化
		Reset()
	End Sub

	/*!
	@brief	予め要素数を指定してList<T>を初期化
	@author	NoWest
	@date	2008/07/13
	@param	リストの要素数
	*/
	Sub List( capacity As Long )
		This.List()
		This.Realloc( capacity )
	End Sub

	/*!
	@brief	既存の配列List<T>を初期化
	@author	NoWest
	@date	2008/07/13
	@param	インデックス
	*/
	Sub List( array As *T, count As Long )
		This.List( count )
		memmove( This.items, array, count * SizeOf(T) )
		This.size = count
	End Sub
	Sub ~List()
	End Sub

	/*!
	@brief	インデクサ
	@author	Daisuke Yamamoto
	@date	2007/08/22
	@param	インデックス
	*/
	Override Sub Operator[] ( index As Long, item As T )
		items[index]=item
	End Sub
	Override Function Operator[] ( index As Long ) As T
		Return items[index]
	End Function

	/*!
	@brief	ポインタ型へのキャスト
	@author	Daisuke Yamamoto
	@date	2007/08/22
	@param	インデックス
	*/
	Function Operator() As *T
		Return items
	End Function


	'----------------------------------------------------------------
	' パブリック プロパティ
	'----------------------------------------------------------------

	/*!
	@brief	Listに格納されている要素の数を取得する
	@author	Daisuke Yamamoto
	@date	2007/08/22
	*/
	Override Function Count() As Long
		Return size
	End Function

	/*!
	@brief	Listが読み込み専用かどうかを取得する
	@author	NoWest
	@date	2008/07/12
	*/
	Override Function IsReadOnly() As Boolean
		Return False
	End Function

	'----------------------------------------------------------------
	' パブリック メソッド
	'----------------------------------------------------------------

	/*!
	@brief	Listの末端に要素を追加する
	@author	Daisuke Yamamoto
	@date	2007/08/22
	@param	追加するオブジェクト
	*/
	Override Sub Add( item As T )
		Realloc( size + 1 )

		items[size] = item
		size++
	End Sub

'	Function AsReadOnly() As ReadOnlyCollection

	/*!
	@brief	Listからすべての要素を削除する
	@author	Daisuke Yamamoto
	@date	2007/08/22
	*/
	Override Sub Clear()
		size = 0
	End Sub

/*	Override Function Contains ( item As T ) As Boolean
		TODO
	End Function*/

	/*!
	@brief	List内から、最初に出現する値のインデックスを取得する
	@author	Daisuke Yamamoto
	@date	2007/08/22
	@return	インデックス（見つからなかったときは-1）
	*/
	Override Function IndexOf( item As T ) As Long
		Dim i As Long
		For i = 0 To ELM(size)
			If items[i].Equals(item) Then
				Return i
			End If
		Next
		Return -1
	End Function

	/*!
	@brief	List内の指定したインデックスの位置に要素を挿入する
	@author	Daisuke Yamamoto
	@date	2007/08/22
	*/
	Override Sub Insert( index As Long, item As T )
		Realloc( size + 1 )
		memmove( items + (index+1)*SizeOf(T), items + index*SizeOf(T), (size-index)*SizeOf(T) )
		items[index] = item
		size++
	End Sub

	/*!
	@brief	List内で最初に出現する値を削除する
	@author	Daisuke Yamamoto
	@date	2007/09/28
	@return	値が削除されたときはTrue、されなかったときはFlaseが返る
	*/
	Override Function Remove( item As T ) As Boolean
		Dim index = IndexOf( item )
		If index = -1 Then
			Return False
		End If

		RemoveAt( index )
		Return True
	End Function

	/*!
	@brief	List内の指定したインデックスの要素を削除する
	@author	Daisuke Yamamoto
	@date	2007/10/03
	@return	値が削除されたときはTrue、されなかったときはFlaseが返る
	*/
	Override Sub RemoveAt( index As Long )
		memmove( items + index*SizeOf(T), items + (index+1)*SizeOf(T), (size-(index+1))*SizeOf(T) )
		Realloc( size - 1 )
		size--
	End Sub

	/*!
	@brief  Listの要素を文字列で返す
	@author OverTaker
	@date   2008/6/26
	@return 文字列
	*/
	Override Function ToString() As String
		Dim string As String
		Dim i As Long
		For i = 0 To This.Count-2
			string += This[i].ToString() + Ex"\r\n"
		Next
		Return string + This[i].ToString()
	End Function

	/*!
	@brief	IEnumeratorインターフェイスを取得する
	@author	Daisuke Yamamoto
	@date	2007/11/19
	@return	IEnumeratorインターフェイスが返る
	*/
	Override Function GetEnumerator() As IEnumerator<T>
		Return This
	End Function

	/*!
	@brief	イテレータのカレントインデックスを増加させる
	@author	Daisuke Yamamoto
	@date	2007/11/19
	@return	上限に達していなければTrueが、達していればFalseが返る
	*/
	Override Function MoveNext() As Boolean
		If currentIndexForEnumerator + 1 >= size Then
			' 上限に達した
			Return False
		End If

		currentIndexForEnumerator ++
		Return True
	End Function

	/*!
	@brief	イテレータをリセットする
	@author	Daisuke Yamamoto
	@date	2007/11/19
	*/
	Override Sub Reset()
		currentIndexForEnumerator = -1
	End Sub

	/*!
	@brief	イテレータのカレントオブジェクトを取得する
	@author	Daisuke Yamamoto
	@date	2007/11/19
	@return	カレントオブジェクトが返る
	*/
	Override Function Current() As T
		If currentIndexForEnumerator = -1 Then
			' MoveNextメソッドがReset後、一度も呼び出されなかった
			Return Nothing
		End If
		Return items[currentIndexForEnumerator]
	End Function
End Class


End Namespace
End Namespace
End Namespace
