
Namespace System
Namespace Collections
Namespace Generic

Class Stack<T>
	Inherits ICollection

	items As *T
	size As Long
	count As Long

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

Public
	Sub Stack ()
		This.items = GC_malloc( 1 )
		Reset()
	End Sub

	Sub Stack ( capacity As Long )
		This.items = GC_malloc( 1 )
		Reset()
		If capacity > 0 Then
			This.size = capacity
			Realloc(capacity)
		End If
	End Sub

	/*!
	@brief	Stackに格納されている要素の数を取得
	@author	NoWest
	@date	2008/07/20
	*/
	Override Function Count () As Long
		Return This.count
	End Function

Public
	/*!
	@brief	Stackからすべての要素を削除する
	@author	NoWest
	@date	2008/07/20
	*/
	Override Sub Clear ()
		This.count = 0
	End Sub

	'ある要素が Stack 内に存在するかどうかを判断
/*	Override Function Contains ( item As T ) As Boolean
		TODO
	End Function*/

	'既存の 1 次元の Array に Stack をコピーします。コピー操作は、配列の指定したインデックスから始まります。 
/*	CopyTo*/

	/*!
	@brief	IEnumeratorインターフェイスを取得する
	@author	NoWest
	@date	2008/07/20
	@return	IEnumeratorインターフェイス
	*/
	Override Function GetEnumerator () As IEnumerator<T>
		Return This
	End Function

	/*!
	@brief	Stackの先頭にあるオブジェクトを削除せずに返します
	@author	NoWest
	@date	2008/07/20
	*/
	Function Peek () As T
		Peek = This.items[ 0 ]
	End Function

 	/*!
	@brief	Stackの先頭にあるオブジェクトを削除し、返します
	@author	NoWest
	@date	2008/07/20
	*/
	Function Pop () As T
		Pop = This.items[ 0 ]
		memmove( items, items + SizeOf(T), (This.count - 1)*SizeOf(T) )
		This.count--
	End Function

	/*!
	@brief	Stackの先頭にオブジェクトを挿入します
	@author	NoWest
	@date	2008/07/20
	*/
	Sub Push ( item As T )
		If This.size < (This.count + 1) Then
			This.size++
			Realloc( This.size )
		End If
		memmove( items + SizeOf(T), items, This.count * SizeOf(T) )
		items[ 0 ] = item
		This.count++
	End Sub

	'Stack を新しい配列にコピーします。 
/*	ToArray*/

	/*!
	@brief	実際の要素数が現在の容量の 90% 未満の場合は、容量をその数に設定します
	@author	NoWest
	@date	2008/07/20
	*/
	Sub TrimExcess ()
		Dim pmemobj = _System_pGC->GetMemoryObjectPtr( items )
		If ( This.size ) * 0.9 > This.count Then
			This.size = This.count
			Realloc( This.size )
		End If
	End Sub


	'------------------------
	'	IEnumeratorの実装
	'------------------------
	currentIndexForEnumerator As Long

	Override Function Current () As T
		If This.currentIndexForEnumerator = -1 Then
			' MoveNextメソッドがReset後、一度も呼び出されなかった
			Return Nothing
		End If
		Return This.items[ This.currentIndexForEnumerator ]
	End Function

	Override Function MoveNext() As Boolean
		If This.currentIndexForEnumerator + 1 >= This.count Then
			' 上限に達した
			Return False
		End If

		This.currentIndexForEnumerator ++
		Return True
	End Function

	Override Sub Reset ()
		This.currentIndexForEnumerator = -1
	End Sub
End Class

End Namespace
End Namespace
End Namespace
