source: trunk/ab5.0/ablib/src/Classes/System/Collections/Generic/List.ab @ 675

Last change on this file since 675 was 675, checked in by イグトランス (egtra), 14 years ago

List<T>のCapacityの増加量を2倍に修正。内部のポインタの取得用のDataプロパティの追加。Containsの実装。

File size: 7.1 KB
Line 
1
2Namespace System
3Namespace Collections
4Namespace Generic
5
6Namespace Detail
7    Class PointerEnumerator<T>
8        Implements IEnumerator<T>
9    Public
10        Sub PointerEnumerator(ptr As *T, count As Long)
11            p = ptr
12            n = count
13            cur = -1
14        End Sub
15
16        Function MoveNext() As Boolean
17            cur++
18            MoveNext = (cur <> n)
19        End Function
20
21        Sub Reset()
22            n = -1
23        End Sub
24
25        Function Current() As T
26            Current = p[cur]
27        End Function
28
29        Virtual Sub Dispose()
30            p = NULL
31            n = 0
32            cur = -1
33        End Sub
34    Private
35        p As *T
36        n As Long
37        cur As Long
38    End Class
39End Namespace
40
41Class List<T>
42    Implements IList<T>
43
44    items As *T
45    capacity As Long
46    count As Long
47
48    Sub Realloc( allocateSize As Long )
49        items = realloc( items, allocateSize * SizeOf(T) )
50        capacity = allocateSize
51    End Sub
52
53    Sub _Initialize( capacity As Long )
54        This.items = GC_malloc( capacity * SizeOf(T) )
55        This.capacity = capacity
56    End Sub
57
58    Sub SetLeastCapacity( leastCapacity As Long )
59        Dim c = This.capacity
60        While c < leastCapacity
61            c *= 2
62        Wend
63        Realloc(c)
64    End Sub
65Public
66    Sub List()
67        _Initialize(16)
68    End Sub
69
70    /*!
71    @brief  予め要素数を指定してList<T>を初期化
72    @author NoWest
73    @date   2008/07/13
74    @param  リストの要素数
75    */
76    Sub List( capacity As Long )
77        _Initialize( capacity )
78    End Sub
79
80    /*!
81    @brief  既存の配列List<T>を初期化
82    @author NoWest
83    @date   2008/07/13
84    @param  基になる配列へのポインタ
85    @param  配列の長さ
86    */
87    Sub List( array As *T, length As Long )
88        _Initialize( length )
89
90        memmove( This.items, array, length * SizeOf(T) )
91        This.count = length
92    End Sub
93
94    /*!
95    @brief  既存のIEnumerable<T>を使用してListを初期化
96    @author NoWest
97    @date   2008/09/22
98    @param  基になるIEnumerable<T>
99    */
100    Sub List ( enumerable As IEnumerable<T> )
101        _Initialize( 1 )
102        Foreach e In enumerable
103'           This.Add(e)
104        Next
105    End Sub
106
107    /*!
108    @brief  インデクサ
109    @author Daisuke Yamamoto
110    @date   2007/08/22
111    @param  インデックス
112    */
113    Sub Operator[] ( index As Long, item As T )
114        Item[index] = item
115    End Sub
116    Function Operator[] ( index As Long ) As T
117        Return Item[index]
118    End Function
119
120    /*!
121    @brief  インデクサ
122    @author Egtra
123    @date   2008/08/04
124    @param  インデックス
125    */
126    Override Sub Item( index As Long, item As T )
127        If 0 <= index And index < capacity Then
128            items[index]=item
129        Else
130            Throw New ArgumentOutOfRangeException("index")
131        End If
132    End Sub
133    Override Function Item( index As Long ) As T
134        If 0 <= index And index < capacity Then
135            Return items[index]
136        Else
137            Throw New ArgumentOutOfRangeException("index")
138        End If
139    End Function
140    /*!
141    @brief  ポインタ型へのキャスト
142    @author Daisuke Yamamoto
143    @date   2007/08/22
144    @param  インデックス
145    */
146    Function Operator() As *T
147        Return items
148    End Function
149
150    /*!
151    @brief  内部の配列へのポインタを取得する
152    @auther Egtra
153    @date   2009/01/13
154    @retrun 内部の配列へのポインタ
155    @pre    Count <> 0
156    */
157    Function Data() As *T
158        Return items
159    End Function
160
161    '----------------------------------------------------------------
162    ' パブリック プロパティ
163    '----------------------------------------------------------------
164
165    /*!
166    @brief  Listに格納されている要素の数を取得する
167    @author Daisuke Yamamoto
168    @date   2007/08/22
169    */
170    Override Function Count() As Long
171        Return This.count
172    End Function
173
174    Const Function Capacity() As Long
175        Return This.capacity
176    End Function
177
178    Sub Capacity(c As Long)
179        If c <> capacity Then
180            If c < capacity Then
181                Throw New ArgumentOutOfRangeException("capacity")
182            Else
183                Realloc(c)
184            End If
185        End If
186    End Sub
187   
188    /*!
189    @brief  Listが読み込み専用かどうかを取得する
190    @author NoWest
191    @date   2008/07/12
192    */
193    Override Function IsReadOnly() As Boolean
194        Return False
195    End Function
196
197    '----------------------------------------------------------------
198    ' パブリック メソッド
199    '----------------------------------------------------------------
200
201    /*!
202    @brief  Listの末端に要素を追加する
203    @author Daisuke Yamamoto
204    @date   2007/08/22
205    @param  追加するオブジェクト
206    */
207    Override Sub Add( item As T )
208        SetLeastCapacity(This.count + 1)
209        This.items[ This.count ] = item
210        This.count++
211    End Sub
212
213    /*!
214    @brief  読み取り専用のListのラッパーを取得
215    @author NoWest
216    @date   2008/09/22
217    */
218/*  Function AsReadOnly() As System.Collections.ObjectModel.ReadOnlyCollection<T>
219        Return New System.Collections.ObjectModel.ReadOnlyCollection<T>(This)
220    End Function*/
221
222    /*!
223    @brief  Listからすべての要素を削除する
224    @author Daisuke Yamamoto
225    @date   2007/08/22
226    */
227    Override Sub Clear()
228        This.count = 0
229    End Sub
230
231    /*!
232    @brief  Listに指定された要素が含まれるか調べる
233    @author Egtra
234    @date   2009/01/13
235    */
236    Function Contains ( item As T ) As Boolean
237        Return IndexOf(item) >= 0
238    End Function
239
240    /*!
241    @brief  List内から、最初に出現する値のインデックスを取得する
242    @author Daisuke Yamamoto
243    @date   2007/08/22
244    @return インデックス(見つからなかったときは-1)
245    */
246    Override Function IndexOf( item As T ) As Long
247        Dim i As Long
248        For i = 0 To ELM( This.count )
249            If items[i].Equals(item) Then
250                Return i
251            End If
252        Next
253        Return -1
254    End Function
255
256    /*!
257    @brief  List内の指定したインデックスの位置に要素を挿入する
258    @author Daisuke Yamamoto
259    @date   2007/08/22
260    */
261    Override Sub Insert( index As Long, item As T )
262        SetLeastCapacity(This.count + 1)
263        memmove( items + (index+1)*SizeOf(T), items + index*SizeOf(T), (This.count - index)*SizeOf(T) )
264        items[index] = item
265        This.count++
266    End Sub
267
268    /*!
269    @brief  List内で最初に出現する値を削除する
270    @author Daisuke Yamamoto
271    @date   2007/09/28
272    @return 値が削除されたときはTrue、されなかったときはFlaseが返る
273    */
274    Override Function Remove( item As T ) As Boolean
275        Dim index = IndexOf( item )
276        If index = -1 Then
277            Return False
278        End If
279
280        removeAtImpl( index )
281        Return True
282    End Function
283
284    /*!
285    @brief  List内の指定したインデックスの要素を削除する
286    @author Daisuke Yamamoto
287    @date   2007/10/03
288    */
289    Override Sub RemoveAt( index As Long )
290        If 0 <= index And index < capacity Then
291            removeAtImpl( index )
292        Else
293            Throw New ArgumentOutOfRangeException("index")
294        End If
295    End Sub
296Private
297    Sub removeAtImpl( index As Long )
298        memmove( items + index*SizeOf(T), items + (index+1)*SizeOf(T), (This.count - (index+1))*SizeOf(T) )
299        This.count--
300    End Sub
301
302Public
303
304    /*!
305    @brief  Listの要素を文字列で返す
306    @author OverTaker
307    @date   2008/6/26
308    @return 文字列
309    */
310    Override Function ToString() As String
311        Dim string = New Text.StringBuilder
312        Dim i As Long
313        For i = 0 To ELM( This.count )
314            string.Append(This[i]).Append(Ex"\r\n")
315        Next
316        Return string.ToString
317    End Function
318
319    /*!
320    @brief  実際の要素数が現在の容量の 90% 未満の場合は、容量をその数に設定します
321    @author NoWest
322    @date   2008/07/20
323    */
324    Sub TrimExcess ()
325        If ( This.capacity ) * 0.9 > This.count Then
326            Realloc( This.count )
327        End If
328    End Sub
329
330    /*!
331    @brief  IEnumeratorインターフェイスを取得する
332    @author Daisuke Yamamoto
333    @date   2007/11/19
334    @return IEnumeratorインターフェイスが返る
335    */
336    Override Function GetEnumerator() As IEnumerator<T>
337        Return New Detail.PointerEnumerator<T>(items, count)
338    End Function
339End Class
340
341
342End Namespace
343End Namespace
344End Namespace
Note: See TracBrowser for help on using the repository browser.