
Namespace System
Namespace Collections
Namespace Generic

Class Stack<T>
	Implements IEnumerable<T>

	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 )
	End Sub

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

Public
	/*!
	@brief	Stackからすべての要素を削除する
	@author	NoWest
	@date	2008/07/20
	*/
	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 New Detail.PointerEnumerator(items, count)
	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
End Class

End Namespace
End Namespace
End Namespace
