~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to contrib/NGit/NGit.Util/RefList.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
This code is derived from jgit (http://eclipse.org/jgit).
 
3
Copyright owners are documented in jgit's IP log.
 
4
 
 
5
This program and the accompanying materials are made available
 
6
under the terms of the Eclipse Distribution License v1.0 which
 
7
accompanies this distribution, is reproduced below, and is
 
8
available at http://www.eclipse.org/org/documents/edl-v10.php
 
9
 
 
10
All rights reserved.
 
11
 
 
12
Redistribution and use in source and binary forms, with or
 
13
without modification, are permitted provided that the following
 
14
conditions are met:
 
15
 
 
16
- Redistributions of source code must retain the above copyright
 
17
  notice, this list of conditions and the following disclaimer.
 
18
 
 
19
- Redistributions in binary form must reproduce the above
 
20
  copyright notice, this list of conditions and the following
 
21
  disclaimer in the documentation and/or other materials provided
 
22
  with the distribution.
 
23
 
 
24
- Neither the name of the Eclipse Foundation, Inc. nor the
 
25
  names of its contributors may be used to endorse or promote
 
26
  products derived from this software without specific prior
 
27
  written permission.
 
28
 
 
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 
30
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
31
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
32
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
33
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
34
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
35
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
36
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
37
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
38
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
39
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
40
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
41
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
42
*/
 
43
 
 
44
using System;
 
45
using System.Collections.Generic;
 
46
using System.Text;
 
47
using NGit;
 
48
using NGit.Util;
 
49
using Sharpen;
 
50
 
 
51
namespace NGit.Util
 
52
{
 
53
        /// <summary>
 
54
        /// Specialized variant of an ArrayList to support a
 
55
        /// <code>RefDatabase</code>
 
56
        /// .
 
57
        /// <p>
 
58
        /// This list is a hybrid of a Map&lt;String,Ref&gt; and of a List&lt;Ref&gt;. It
 
59
        /// tracks reference instances by name by keeping them sorted and performing
 
60
        /// binary search to locate an entry. Lookup time is O(log N), but addition and
 
61
        /// removal is O(N + log N) due to the list expansion or contraction costs.
 
62
        /// <p>
 
63
        /// This list type is copy-on-write. Mutation methods return a new copy of the
 
64
        /// list, leaving
 
65
        /// <code>this</code>
 
66
        /// unmodified. As a result we cannot easily implement
 
67
        /// the
 
68
        /// <see cref="System.Collections.IList{E}">System.Collections.IList&lt;E&gt;</see>
 
69
        /// interface contract.
 
70
        /// </summary>
 
71
        /// <?></?>
 
72
        public class RefList<T> : Iterable<Ref> where T:Ref
 
73
        {
 
74
                private static readonly NGit.Util.RefList<Ref> EMPTY = new NGit.Util.RefList<Ref>
 
75
                        (new Ref[0], 0);
 
76
 
 
77
                /// <returns>an empty unmodifiable reference list.</returns>
 
78
                /// <?></?>
 
79
                public static NGit.Util.RefList<T> EmptyList<T>() where T:Ref
 
80
                {
 
81
                        return new RefList<T>(new Ref[0], 0);
 
82
                }
 
83
 
 
84
                public static NGit.Util.RefList<Ref> EmptyList()
 
85
                {
 
86
                        return RefList<T>.EMPTY;
 
87
                }
 
88
                
 
89
                private readonly Ref[] list;
 
90
 
 
91
                private readonly int cnt;
 
92
 
 
93
                internal RefList(Ref[] list, int cnt)
 
94
                {
 
95
                        this.list = list;
 
96
                        this.cnt = cnt;
 
97
                }
 
98
 
 
99
                /// <summary>Initialize this list to use the same backing array as another list.</summary>
 
100
                /// <remarks>Initialize this list to use the same backing array as another list.</remarks>
 
101
                /// <param name="src">the source list.</param>
 
102
                protected internal RefList(NGit.Util.RefList<T> src)
 
103
                {
 
104
                        this.list = src.list;
 
105
                        this.cnt = src.cnt;
 
106
                }
 
107
 
 
108
                public override Sharpen.Iterator<Ref> Iterator()
 
109
                {
 
110
                        return new _Iterator_104(this);
 
111
                }
 
112
 
 
113
                private sealed class _Iterator_104 : Sharpen.Iterator<Ref>
 
114
                {
 
115
                        public _Iterator_104(RefList<T> _enclosing)
 
116
                        {
 
117
                                this._enclosing = _enclosing;
 
118
                        }
 
119
 
 
120
                        private int idx;
 
121
 
 
122
                        public override bool HasNext()
 
123
                        {
 
124
                                return this.idx < this._enclosing.cnt;
 
125
                        }
 
126
 
 
127
                        public override Ref Next()
 
128
                        {
 
129
                                if (this.idx < this._enclosing.cnt)
 
130
                                {
 
131
                                        return this._enclosing.list[this.idx++];
 
132
                                }
 
133
                                throw new NoSuchElementException();
 
134
                        }
 
135
 
 
136
                        public override void Remove()
 
137
                        {
 
138
                                throw new NotSupportedException();
 
139
                        }
 
140
 
 
141
                        private readonly RefList<T> _enclosing;
 
142
                }
 
143
 
 
144
                /// <returns>
 
145
                /// this cast as an immutable, standard
 
146
                /// <see cref="System.Collections.IList{E}">System.Collections.IList&lt;E&gt;</see>
 
147
                /// .
 
148
                /// </returns>
 
149
                public IList<Ref> AsList()
 
150
                {
 
151
                        IList<Ref> r = Arrays.AsList(list).SubList(0, cnt);
 
152
                        return Sharpen.Collections.UnmodifiableList(r);
 
153
                }
 
154
 
 
155
                /// <returns>number of items in this list.</returns>
 
156
                public int Size()
 
157
                {
 
158
                        return cnt;
 
159
                }
 
160
 
 
161
                /// <returns>true if the size of this list is 0.</returns>
 
162
                public bool IsEmpty()
 
163
                {
 
164
                        return cnt == 0;
 
165
                }
 
166
 
 
167
                /// <summary>Locate an entry by name.</summary>
 
168
                /// <remarks>Locate an entry by name.</remarks>
 
169
                /// <param name="name">the name of the reference to find.</param>
 
170
                /// <returns>
 
171
                /// the index the reference is at. If the entry is not present
 
172
                /// returns a negative value. The insertion position for the given
 
173
                /// name can be computed from
 
174
                /// <code>-(index + 1)</code>
 
175
                /// .
 
176
                /// </returns>
 
177
                public int Find(string name)
 
178
                {
 
179
                        int high = cnt;
 
180
                        if (high == 0)
 
181
                        {
 
182
                                return -1;
 
183
                        }
 
184
                        int low = 0;
 
185
                        do
 
186
                        {
 
187
                                int mid = (int)(((uint)(low + high)) >> 1);
 
188
                                int cmp = RefComparator.CompareTo(list[mid], name);
 
189
                                if (cmp < 0)
 
190
                                {
 
191
                                        low = mid + 1;
 
192
                                }
 
193
                                else
 
194
                                {
 
195
                                        if (cmp == 0)
 
196
                                        {
 
197
                                                return mid;
 
198
                                        }
 
199
                                        else
 
200
                                        {
 
201
                                                high = mid;
 
202
                                        }
 
203
                                }
 
204
                        }
 
205
                        while (low < high);
 
206
                        return -(low + 1);
 
207
                }
 
208
 
 
209
                /// <summary>Determine if a reference is present.</summary>
 
210
                /// <remarks>Determine if a reference is present.</remarks>
 
211
                /// <param name="name">name of the reference to find.</param>
 
212
                /// <returns>true if the reference is present; false if it is not.</returns>
 
213
                public bool Contains(string name)
 
214
                {
 
215
                        return 0 <= Find(name);
 
216
                }
 
217
 
 
218
                /// <summary>Get a reference object by name.</summary>
 
219
                /// <remarks>Get a reference object by name.</remarks>
 
220
                /// <param name="name">the name of the reference.</param>
 
221
                /// <returns>the reference object; null if it does not exist in this list.</returns>
 
222
                public T Get(string name)
 
223
                {
 
224
                        int idx = Find(name);
 
225
                        return 0 <= idx ? Get(idx) : default(T);
 
226
                }
 
227
 
 
228
                /// <summary>Get the reference at a particular index.</summary>
 
229
                /// <remarks>Get the reference at a particular index.</remarks>
 
230
                /// <param name="idx">
 
231
                /// the index to obtain. Must be
 
232
                /// <code>0 &lt;= idx &lt; size()</code>
 
233
                /// .
 
234
                /// </param>
 
235
                /// <returns>the reference value, never null.</returns>
 
236
                public T Get(int idx)
 
237
                {
 
238
                        return (T)list[idx];
 
239
                }
 
240
 
 
241
                internal static RefList<Ref> Copy<U>(RefList<U> other) where U: Ref
 
242
                {
 
243
                    return new RefList<Ref>(other.list, other.cnt);
 
244
                }
 
245
 
 
246
                /// <summary>
 
247
                /// Obtain a builder initialized with the first
 
248
                /// <code>n</code>
 
249
                /// elements.
 
250
                /// <p>
 
251
                /// Copies the first
 
252
                /// <code>n</code>
 
253
                /// elements from this list into a new builder,
 
254
                /// which can be used by the caller to add additional elements.
 
255
                /// </summary>
 
256
                /// <param name="n">the number of elements to copy.</param>
 
257
                /// <returns>
 
258
                /// a new builder with the first
 
259
                /// <code>n</code>
 
260
                /// elements already added.
 
261
                /// </returns>
 
262
                public RefListBuilder<T> Copy(int n)
 
263
                {
 
264
                        RefListBuilder<T> r = new RefListBuilder<T>(Math.Max(16, n));
 
265
                        r.AddAll(list, 0, n);
 
266
                        return r;
 
267
                }
 
268
 
 
269
                /// <summary>Obtain a new copy of the list after changing one element.</summary>
 
270
                /// <remarks>
 
271
                /// Obtain a new copy of the list after changing one element.
 
272
                /// <p>
 
273
                /// This list instance is not affected by the replacement. Because this
 
274
                /// method copies the entire list, it runs in O(N) time.
 
275
                /// </remarks>
 
276
                /// <param name="idx">index of the element to change.</param>
 
277
                /// <param name="ref">the new value, must not be null.</param>
 
278
                /// <returns>
 
279
                /// copy of this list, after replacing
 
280
                /// <code>idx</code>
 
281
                /// with
 
282
                /// <code>ref</code>
 
283
                /// .
 
284
                /// </returns>
 
285
                public NGit.Util.RefList<T> Set(int idx, T @ref)
 
286
                {
 
287
                        Ref[] newList = new Ref[cnt];
 
288
                        System.Array.Copy(list, 0, newList, 0, cnt);
 
289
                        newList[idx] = @ref;
 
290
                        return new NGit.Util.RefList<T>(newList, cnt);
 
291
                }
 
292
 
 
293
                /// <summary>Add an item at a specific index.</summary>
 
294
                /// <remarks>
 
295
                /// Add an item at a specific index.
 
296
                /// <p>
 
297
                /// This list instance is not affected by the addition. Because this method
 
298
                /// copies the entire list, it runs in O(N) time.
 
299
                /// </remarks>
 
300
                /// <param name="idx">
 
301
                /// position to add the item at. If negative the method assumes it
 
302
                /// was a direct return value from
 
303
                /// <see cref="RefList{T}.Find(string)">RefList&lt;T&gt;.Find(string)</see>
 
304
                /// and will
 
305
                /// adjust it to the correct position.
 
306
                /// </param>
 
307
                /// <param name="ref">the new reference to insert.</param>
 
308
                /// <returns>
 
309
                /// copy of this list, after making space for and adding
 
310
                /// <code>ref</code>
 
311
                /// .
 
312
                /// </returns>
 
313
                public NGit.Util.RefList<T> Add(int idx, T @ref)
 
314
                {
 
315
                        if (idx < 0)
 
316
                        {
 
317
                                idx = -(idx + 1);
 
318
                        }
 
319
                        Ref[] newList = new Ref[cnt + 1];
 
320
                        if (0 < idx)
 
321
                        {
 
322
                                System.Array.Copy(list, 0, newList, 0, idx);
 
323
                        }
 
324
                        newList[idx] = @ref;
 
325
                        if (idx < cnt)
 
326
                        {
 
327
                                System.Array.Copy(list, idx, newList, idx + 1, cnt - idx);
 
328
                        }
 
329
                        return new NGit.Util.RefList<T>(newList, cnt + 1);
 
330
                }
 
331
 
 
332
                /// <summary>Remove an item at a specific index.</summary>
 
333
                /// <remarks>
 
334
                /// Remove an item at a specific index.
 
335
                /// <p>
 
336
                /// This list instance is not affected by the addition. Because this method
 
337
                /// copies the entire list, it runs in O(N) time.
 
338
                /// </remarks>
 
339
                /// <param name="idx">position to remove the item from.</param>
 
340
                /// <returns>
 
341
                /// copy of this list, after making removing the item at
 
342
                /// <code>idx</code>
 
343
                /// .
 
344
                /// </returns>
 
345
                public NGit.Util.RefList<T> Remove(int idx)
 
346
                {
 
347
                        if (cnt == 1)
 
348
                        {
 
349
                                return EmptyList<T>();
 
350
                        }
 
351
                        Ref[] newList = new Ref[cnt - 1];
 
352
                        if (0 < idx)
 
353
                        {
 
354
                                System.Array.Copy(list, 0, newList, 0, idx);
 
355
                        }
 
356
                        if (idx + 1 < cnt)
 
357
                        {
 
358
                                System.Array.Copy(list, idx + 1, newList, idx, cnt - (idx + 1));
 
359
                        }
 
360
                        return new NGit.Util.RefList<T>(newList, cnt - 1);
 
361
                }
 
362
 
 
363
                /// <summary>Store a reference, adding or replacing as necessary.</summary>
 
364
                /// <remarks>
 
365
                /// Store a reference, adding or replacing as necessary.
 
366
                /// <p>
 
367
                /// This list instance is not affected by the store. The correct position is
 
368
                /// determined, and the item is added if missing, or replaced if existing.
 
369
                /// Because this method copies the entire list, it runs in O(N + log N) time.
 
370
                /// </remarks>
 
371
                /// <param name="ref">the reference to store.</param>
 
372
                /// <returns>copy of this list, after performing the addition or replacement.</returns>
 
373
                public NGit.Util.RefList<T> Put(T @ref)
 
374
                {
 
375
                        int idx = Find(@ref.GetName());
 
376
                        if (0 <= idx)
 
377
                        {
 
378
                                return Set(idx, @ref);
 
379
                        }
 
380
                        return Add(idx, @ref);
 
381
                }
 
382
 
 
383
                public override string ToString()
 
384
                {
 
385
                        StringBuilder r = new StringBuilder();
 
386
                        r.Append('[');
 
387
                        if (cnt > 0)
 
388
                        {
 
389
                                r.Append(list[0]);
 
390
                                for (int i = 1; i < cnt; i++)
 
391
                                {
 
392
                                        r.Append(", ");
 
393
                                        r.Append(list[i]);
 
394
                                }
 
395
                        }
 
396
                        r.Append(']');
 
397
                        return r.ToString();
 
398
                }
 
399
        }
 
400
 
 
401
        /// <summary>Builder to facilitate fast construction of an immutable RefList.</summary>
 
402
        /// <remarks>Builder to facilitate fast construction of an immutable RefList.</remarks>
 
403
        /// <?></?>
 
404
        public class RefListBuilder<T> where T:Ref
 
405
        {
 
406
                private Ref[] list;
 
407
 
 
408
                private int size;
 
409
 
 
410
                /// <summary>Create an empty list ready for items to be added.</summary>
 
411
                /// <remarks>Create an empty list ready for items to be added.</remarks>
 
412
                public RefListBuilder() : this(16)
 
413
                {
 
414
                }
 
415
 
 
416
                /// <summary>Create an empty list with at least the specified capacity.</summary>
 
417
                /// <remarks>Create an empty list with at least the specified capacity.</remarks>
 
418
                /// <param name="capacity">the new capacity.</param>
 
419
                public RefListBuilder(int capacity)
 
420
                {
 
421
                        list = new Ref[capacity];
 
422
                }
 
423
 
 
424
                /// <returns>number of items in this builder's internal collection.</returns>
 
425
                public virtual int Size()
 
426
                {
 
427
                        return size;
 
428
                }
 
429
 
 
430
                /// <summary>Get the reference at a particular index.</summary>
 
431
                /// <remarks>Get the reference at a particular index.</remarks>
 
432
                /// <param name="idx">
 
433
                /// the index to obtain. Must be
 
434
                /// <code>0 &lt;= idx &lt; size()</code>
 
435
                /// .
 
436
                /// </param>
 
437
                /// <returns>the reference value, never null.</returns>
 
438
                public virtual T Get(int idx)
 
439
                {
 
440
                        return (T)list[idx];
 
441
                }
 
442
 
 
443
                /// <summary>Remove an item at a specific index.</summary>
 
444
                /// <remarks>Remove an item at a specific index.</remarks>
 
445
                /// <param name="idx">position to remove the item from.</param>
 
446
                public virtual void Remove(int idx)
 
447
                {
 
448
                        System.Array.Copy(list, idx + 1, list, idx, size - (idx + 1));
 
449
                        size--;
 
450
                }
 
451
 
 
452
                /// <summary>Add the reference to the end of the array.</summary>
 
453
                /// <remarks>
 
454
                /// Add the reference to the end of the array.
 
455
                /// <p>
 
456
                /// References must be added in sort order, or the array must be sorted
 
457
                /// after additions are complete using
 
458
                /// <see cref="Builder{T}.Sort()">Builder&lt;T&gt;.Sort()</see>
 
459
                /// .
 
460
                /// </remarks>
 
461
                /// <param name="ref"></param>
 
462
                public virtual void Add(T @ref)
 
463
                {
 
464
                        if (list.Length == size)
 
465
                        {
 
466
                                Ref[] n = new Ref[size * 2];
 
467
                                System.Array.Copy(list, 0, n, 0, size);
 
468
                                list = n;
 
469
                        }
 
470
                        list[size++] = @ref;
 
471
                }
 
472
 
 
473
                /// <summary>Add all items from a source array.</summary>
 
474
                /// <remarks>
 
475
                /// Add all items from a source array.
 
476
                /// <p>
 
477
                /// References must be added in sort order, or the array must be sorted
 
478
                /// after additions are complete using
 
479
                /// <see cref="Builder{T}.Sort()">Builder&lt;T&gt;.Sort()</see>
 
480
                /// .
 
481
                /// </remarks>
 
482
                /// <param name="src">the source array.</param>
 
483
                /// <param name="off">
 
484
                /// position within
 
485
                /// <code>src</code>
 
486
                /// to start copying from.
 
487
                /// </param>
 
488
                /// <param name="cnt">
 
489
                /// number of items to copy from
 
490
                /// <code>src</code>
 
491
                /// .
 
492
                /// </param>
 
493
                public virtual void AddAll(Ref[] src, int off, int cnt)
 
494
                {
 
495
                        if (list.Length < size + cnt)
 
496
                        {
 
497
                                Ref[] n = new Ref[Math.Max(size * 2, size + cnt)];
 
498
                                System.Array.Copy(list, 0, n, 0, size);
 
499
                                list = n;
 
500
                        }
 
501
                        System.Array.Copy(src, off, list, size, cnt);
 
502
                        size += cnt;
 
503
                }
 
504
 
 
505
                /// <summary>Replace a single existing element.</summary>
 
506
                /// <remarks>Replace a single existing element.</remarks>
 
507
                /// <param name="idx">index, must have already been added previously.</param>
 
508
                /// <param name="ref">the new reference.</param>
 
509
                public virtual void Set(int idx, T @ref)
 
510
                {
 
511
                        list[idx] = @ref;
 
512
                }
 
513
 
 
514
                /// <summary>Sort the list's backing array in-place.</summary>
 
515
                /// <remarks>Sort the list's backing array in-place.</remarks>
 
516
                public virtual void Sort()
 
517
                {
 
518
                        Arrays.Sort(list, 0, size, RefComparator.INSTANCE);
 
519
                }
 
520
 
 
521
                /// <returns>an unmodifiable list using this collection's backing array.</returns>
 
522
                public virtual RefList<T> ToRefList()
 
523
                {
 
524
                        return new RefList<T>(list, size);
 
525
                }
 
526
 
 
527
                public override string ToString()
 
528
                {
 
529
                        return ToRefList().ToString();
 
530
                }
 
531
        }
 
532
 
 
533
        internal class RefList : RefList<Ref>
 
534
        {
 
535
                // Methods
 
536
                public RefList() : base(new Ref[0], 0)
 
537
                {
 
538
                }
 
539
        }
 
540
        
 
541
        
 
542
}