Namespace System Namespace Collections Namespace Generic Namespace Detail Class PointerEnumerator Implements IEnumerator Public Sub PointerEnumerator(ptr As *T, count As Long) p = ptr n = count cur = -1 End Sub Function MoveNext() As Boolean cur++ MoveNext = (cur <> n) End Function Sub Reset() n = -1 End Sub Function Current() As T Current = p[cur] End Function Virtual Sub Dispose() p = NULL n = 0 cur = -1 End Sub Private p As *T n As Long cur As Long End Class End Namespace Class List Implements IList items As *T capacity As Long count As Long Sub Realloc( allocateSize As Long ) items = realloc( items, allocateSize * SizeOf(T) ) capacity = allocateSize End Sub Sub _Initialize( capacity As Long ) This.items = GC_malloc( capacity * SizeOf(T) ) This.capacity = capacity End Sub Sub SetLeastCapacity( leastCapacity As Long ) Dim c = This.capacity While c < leastCapacity c *= 2 Wend Realloc(c) End Sub Public Sub List() _Initialize(16) End Sub /*! @brief 予め要素数を指定してListを初期化 @author NoWest @date 2008/07/13 @param リストの要素数 */ Sub List( capacity As Long ) _Initialize( capacity ) End Sub /*! @brief 既存の配列Listを初期化 @author NoWest @date 2008/07/13 @param 基になる配列へのポインタ @param 配列の長さ */ Sub List( array As *T, length As Long ) _Initialize( length ) memmove( This.items, array, length * SizeOf(T) ) This.count = length End Sub /*! @brief 既存のIEnumerableを使用してListを初期化 @author NoWest @date 2008/09/22 @param 基になるIEnumerable */ Sub List ( enumerable As IEnumerable ) _Initialize( 1 ) Foreach e In enumerable ' This.Add(e) Next End Sub /*! @brief インデクサ @author Daisuke Yamamoto @date 2007/08/22 @param インデックス */ Sub Operator[] ( index As Long, item As T ) Item[index] = item End Sub Function Operator[] ( index As Long ) As T Return Item[index] End Function /*! @brief インデクサ @author Egtra @date 2008/08/04 @param インデックス */ Override Sub Item( index As Long, item As T ) If 0 <= index And index < capacity Then items[index]=item Else Throw New ArgumentOutOfRangeException("index") End If End Sub Override Function Item( index As Long ) As T If 0 <= index And index < capacity Then Return items[index] Else Throw New ArgumentOutOfRangeException("index") End If End Function /*! @brief ポインタ型へのキャスト @author Daisuke Yamamoto @date 2007/08/22 @param インデックス */ Function Operator() As *T Return items End Function /*! @brief 内部の配列へのポインタを取得する @auther Egtra @date 2009/01/13 @retrun 内部の配列へのポインタ @pre Count <> 0 */ Function Data() As *T Return items End Function '---------------------------------------------------------------- ' パブリック プロパティ '---------------------------------------------------------------- /*! @brief Listに格納されている要素の数を取得する @author Daisuke Yamamoto @date 2007/08/22 */ Override Function Count() As Long Return This.count End Function Const Function Capacity() As Long Return This.capacity End Function Sub Capacity(c As Long) If c <> capacity Then If c < capacity Then Throw New ArgumentOutOfRangeException("capacity") Else Realloc(c) End If End If End Sub /*! @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 ) SetLeastCapacity(This.count + 1) This.items[ This.count ] = item This.count++ End Sub /*! @brief 読み取り専用のListのラッパーを取得 @author NoWest @date 2008/09/22 */ /* Function AsReadOnly() As System.Collections.ObjectModel.ReadOnlyCollection Return New System.Collections.ObjectModel.ReadOnlyCollection(This) End Function*/ /*! @brief Listからすべての要素を削除する @author Daisuke Yamamoto @date 2007/08/22 */ Override Sub Clear() This.count = 0 End Sub /*! @brief Listに指定された要素が含まれるか調べる @author Egtra @date 2009/01/13 */ Function Contains ( item As T ) As Boolean Return IndexOf(item) >= 0 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( This.count ) 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 ) SetLeastCapacity(This.count + 1) memmove( items + (index+1)*SizeOf(T), items + index*SizeOf(T), (This.count - index)*SizeOf(T) ) items[index] = item This.count++ 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 removeAtImpl( index ) Return True End Function /*! @brief List内の指定したインデックスの要素を削除する @author Daisuke Yamamoto @date 2007/10/03 */ Override Sub RemoveAt( index As Long ) If 0 <= index And index < capacity Then removeAtImpl( index ) Else Throw New ArgumentOutOfRangeException("index") End If End Sub Private Sub removeAtImpl( index As Long ) memmove( items + index*SizeOf(T), items + (index+1)*SizeOf(T), (This.count - (index+1))*SizeOf(T) ) This.count-- End Sub Public /*! @brief Listの要素を文字列で返す @author OverTaker @date 2008/6/26 @return 文字列 */ Override Function ToString() As String Dim string = New Text.StringBuilder Dim i As Long For i = 0 To ELM( This.count ) string.Append(This[i]).Append(Ex"\r\n") Next Return string.ToString End Function /*! @brief 実際の要素数が現在の容量の 90% 未満の場合は、容量をその数に設定します @author NoWest @date 2008/07/20 */ Sub TrimExcess () If ( This.capacity ) * 0.9 > This.count Then Realloc( This.count ) End If End Sub /*! @brief IEnumeratorインターフェイスを取得する @author Daisuke Yamamoto @date 2007/11/19 @return IEnumeratorインターフェイスが返る */ Override Function GetEnumerator() As IEnumerator Return New Detail.PointerEnumerator(items, count) End Function End Class End Namespace End Namespace End Namespace