~ubuntu-branches/ubuntu/saucy/monodevelop/saucy-proposed

« back to all changes in this revision

Viewing changes to src/core/MonoDevelop.Ide/MonoDevelop.Components.Diff/Diff.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2010-09-10 16:54:48 UTC
  • mfrom: (19.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20100910165448-0rybfk25zd4o9431
Tags: 2.4+dfsg-2
* debian/patches/inject_Mono.Debugger.Soft_source.patch,
  debian/patches/use_system_Mono.Debugger.Soft.patch,
  debian/control:
  + Build against system Soft Debugger, since we now have a new
    enough Mono to match MonoDevelop's required API

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Diff Algorithm in C#
 
3
 * Based on Tye McQueen's Algorithm::Diff Perl module version 1.19_01
 
4
 * Converted to C# by Joshua Tauberer <tauberer@for.net>
 
5
 * 
 
6
 * The Perl module's copyright notice:
 
7
 * Parts Copyright (c) 2000-2004 Ned Konz.  All rights reserved.
 
8
 * Parts by Tye McQueen.
 
9
 *
 
10
 * The Perl module's readme has a ridiculously long list of
 
11
 * thanks for all of the previous authors, who are:
 
12
 * Mario Wolczko (author of SmallTalk code the module is based on)
 
13
 * Ned Konz
 
14
 * Mark-Jason Dominus
 
15
 * Mike Schilli
 
16
 * Amir Karger
 
17
 * Christian Murphy
 
18
 *
 
19
 * The Perl module was released under the Perl Artistic License,
 
20
 * and I leave my additions in the public domain, so I leave
 
21
 * it up to you to figure out what you need to do if you want
 
22
 * to distribute this file in some form.
 
23
 */
 
24
 
 
25
using System;
 
26
using System.Collections;
 
27
using System.Collections.Generic;
 
28
using System.Text;
 
29
 
 
30
namespace MonoDevelop.Components.Diff {
 
31
        public interface IDiff : IEnumerable {
 
32
                IList Left { get; }
 
33
                IList Right { get; }
 
34
        }
 
35
        
 
36
        public abstract class Hunk {
 
37
                internal Hunk() { }
 
38
                
 
39
                public abstract int ChangedLists { get; }
 
40
                
 
41
                public abstract bool Same { get; }
 
42
                public abstract bool Conflict { get; }
 
43
                
 
44
                public abstract bool IsSame(int index);
 
45
 
 
46
                public abstract Range Original();
 
47
                public abstract Range Changes(int index);
 
48
                
 
49
                public int MaxLines() {
 
50
                        int m = Original().Count;
 
51
                        for (int i = 0; i < ChangedLists; i++)
 
52
                                if (Changes(i).Count > m)
 
53
                                        m = Changes(i).Count;
 
54
                        return m;
 
55
                }
 
56
        }
 
57
        
 
58
        public class Diff : IDiff {
 
59
                internal IList left, right;
 
60
                IComparer comparer;
 
61
                IEqualityComparer hashcoder;
 
62
                
 
63
                public IList Left { get { return left; } }
 
64
                public  IList Right { get { return right; } }
 
65
                
 
66
                private class Trio {
 
67
                        public Trio a;
 
68
                        public int b, c;
 
69
                        public Trio(Trio a, int b, int c) {
 
70
                                this.a = a;
 
71
                                this.b = b;
 
72
                                this.c = c;
 
73
                        }
 
74
                }
 
75
                
 
76
                public class Hunk : MonoDevelop.Components.Diff.Hunk {
 
77
                        IList left, right;
 
78
                        int s1start, s1end, s2start, s2end;
 
79
                        bool same;
 
80
                        
 
81
                        internal Hunk(IList left, IList right, int s1start, int s1end, int s2start, int s2end, bool same) {
 
82
                                this.left = left;
 
83
                                this.right = right;
 
84
                                this.s1start = s1start;
 
85
                                this.s1end = s1end;
 
86
                                this.s2start = s2start;
 
87
                                this.s2end = s2end;
 
88
                                this.same = same;
 
89
                        }
 
90
                        
 
91
                        internal void SetLists(IList left, IList right) {
 
92
                                this.left = left;
 
93
                                this.right = right;
 
94
                        }
 
95
                        
 
96
                        public override int ChangedLists { get { return 1; } }
 
97
 
 
98
                        public override bool Same { get { return same; } }
 
99
                        
 
100
                        public override bool Conflict { get { return false; } }
 
101
                        
 
102
                        public override bool IsSame(int index) {
 
103
                                if (index != 0) throw new ArgumentException();
 
104
                                return Same;
 
105
                        }
 
106
 
 
107
                        private Range get(int seq) {
 
108
                                int start = (seq==1?s1start:s2start);
 
109
                                int end = (seq==1?s1end:s2end);
 
110
                                IList list = (seq==1?left:right);
 
111
                                if (end < start) return new Range(list, start, 0);
 
112
                                return new Range(list, start, end-start+1);
 
113
                        }
 
114
                        
 
115
                        public Range Left { get { return get(1); } }
 
116
                        public Range Right { get { return get(2); } }
 
117
 
 
118
                        public override Range Original() { return Left; }
 
119
                        public override Range Changes(int index) {
 
120
                                if (index != 0) throw new ArgumentException();
 
121
                                return Right;
 
122
                        }
 
123
                                
 
124
                        public override int GetHashCode() {
 
125
                                return unchecked(s1start + s1end + s2start + s2end);
 
126
                        }
 
127
                        
 
128
                        public override bool Equals(object o) {
 
129
                                Hunk h = o as Hunk;
 
130
                                return
 
131
                                        s1start == h.s1start &&
 
132
                                        s1start == h.s1end &&
 
133
                                        s1start == h.s2start &&
 
134
                                        s1start == h.s2end &&
 
135
                                        same == h.same;
 
136
                        }
 
137
                        
 
138
                        public override string ToString() {
 
139
                                if (left == null || right == null)
 
140
                                        return base.ToString();
 
141
                                return DiffString();
 
142
                        }
 
143
                        
 
144
                        public string DiffString() {
 
145
                                if (left == null || right == null)
 
146
                                        throw new InvalidOperationException("This hunk is based on a patch which does not have the compared data.");
 
147
                                        
 
148
                                StringBuilder ret = new StringBuilder();
 
149
                                
 
150
                                if (Same) {
 
151
                                        foreach (object item in Left) {
 
152
                                                ret.Append(' ');
 
153
                                                ret.Append(item.ToString());
 
154
                                                ret.Append(Environment.NewLine);
 
155
                                        }
 
156
                                } else {
 
157
                                        foreach (object item in Left) {
 
158
                                                ret.Append('<');
 
159
                                                ret.Append(item.ToString());
 
160
                                                ret.Append(Environment.NewLine);
 
161
                                        }
 
162
                                        foreach (object item in Right) {
 
163
                                                ret.Append('>');
 
164
                                                ret.Append(item.ToString());
 
165
                                                ret.Append(Environment.NewLine);
 
166
                                        }
 
167
                                }
 
168
                                
 
169
                                return ret.ToString();
 
170
                        }
 
171
                        
 
172
                        internal Hunk Crop(int shiftstart, int shiftend) {
 
173
                                return new Diff.Hunk(left, right, Left.Start+shiftstart, Left.End-shiftend, Right.Start+shiftstart, Right.End-shiftend, same);
 
174
                        }
 
175
                        
 
176
                        internal Hunk Reverse() {
 
177
                                return new Diff.Hunk(right, left, Right.Start, Right.End, Left.Start, Left.End, same);
 
178
                        }
 
179
                }
 
180
        
 
181
                public Diff(IList left, IList right, IComparer comparer, IEqualityComparer hashcoder) {
 
182
                        this.left = left;
 
183
                        this.right = right;
 
184
                        this.comparer = comparer;
 
185
                        this.hashcoder = hashcoder;
 
186
                        init();
 
187
                }
 
188
                
 
189
                public Diff(string leftFile, string rightFile, bool caseSensitive, bool compareWhitespace)
 
190
                        : this(UnifiedDiff.LoadFileLines(leftFile), UnifiedDiff.LoadFileLines(rightFile), caseSensitive, compareWhitespace) {
 
191
                }
 
192
                
 
193
                public Diff(string[] left, string[] right, bool caseSensitive, bool compareWhitespace) 
 
194
                        : this(
 
195
                                StripWhitespace(left, !compareWhitespace),
 
196
                                StripWhitespace(right, !compareWhitespace),
 
197
                                caseSensitive ? (IComparer)Comparer.Default : (IComparer)CaseInsensitiveComparer.Default,
 
198
                                caseSensitive ? null : StringComparer.InvariantCultureIgnoreCase
 
199
                                ) {
 
200
                }
 
201
                
 
202
                ////////////////////////////////////////////////////////////
 
203
                
 
204
                
 
205
                private static string[] StripWhitespace(string[] lines, bool strip) {
 
206
                        if (!strip) return lines;
 
207
                        string[] ret = new string[lines.Length];
 
208
                        for (int i = 0; i < lines.Length; i++) {
 
209
                                StringBuilder sb = new StringBuilder();
 
210
                                foreach (char c in lines[i])
 
211
                                        if (!char.IsWhiteSpace(c))
 
212
                                                sb.Append(c);
 
213
                                ret[i] = sb.ToString();
 
214
                        }
 
215
                        return ret;
 
216
                }
 
217
 
 
218
                ////////////////////////////////////////////////////////////
 
219
                
 
220
                IEnumerator IEnumerable.GetEnumerator() {
 
221
                        if (cdif == null)
 
222
                                throw new InvalidOperationException("No comparison has been performed.");
 
223
                        return new Enumerator(this);
 
224
                }
 
225
                
 
226
                public override string ToString() {
 
227
                        System.IO.StringWriter w = new System.IO.StringWriter();
 
228
                        UnifiedDiff.WriteUnifiedDiff(this, w);
 
229
                        return w.ToString();
 
230
                }
 
231
                
 
232
                public Patch CreatePatch() {
 
233
                        int ctr = 0;
 
234
                        foreach (Hunk hunk in this)
 
235
                                if (!hunk.Same)
 
236
                                        ctr += hunk.Right.Count;
 
237
                                
 
238
                        object[] rightData = new object[ctr];
 
239
                                
 
240
                        ArrayList hunks = new ArrayList();
 
241
                        ctr = 0;
 
242
                        foreach (Hunk hunk in this) {
 
243
                                if (hunk.Same) {
 
244
                                        hunks.Add(new Patch.Hunk(rightData, hunk.Left.Start, hunk.Left.Count, 0, 0, true));
 
245
                                } else {
 
246
                                        hunks.Add(new Patch.Hunk(rightData, hunk.Left.Start, hunk.Left.Count, ctr, hunk.Right.Count, false));
 
247
                                        for (int i = 0; i < hunk.Right.Count; i++)
 
248
                                                rightData[ctr++] = hunk.Right[i];
 
249
                                }
 
250
                        }
 
251
                        
 
252
                        
 
253
                        return new Patch((Patch.Hunk[])hunks.ToArray(typeof(Hunk)));
 
254
                }
 
255
 
 
256
                /*
 
257
                # McIlroy-Hunt diff algorithm
 
258
                # Adapted from the Smalltalk code of Mario I. Wolczko, <mario@wolczko.com>
 
259
                # by Ned Konz, perl@bike-nomad.com
 
260
                # Updates by Tye McQueen, http://perlmonks.org/?node=tye
 
261
                
 
262
                # Create a hash that maps each element of $aCollection to the set of
 
263
                # positions it occupies in $aCollection, restricted to the elements
 
264
                # within the range of indexes specified by $start and $end.
 
265
                # The fourth parameter is a subroutine reference that will be called to
 
266
                # generate a string to use as a key.
 
267
                # Additional parameters, if any, will be passed to this subroutine.
 
268
                #
 
269
                # my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen );
 
270
                */
 
271
 
 
272
                Hashtable _withPositionsOfInInterval(IList aCollection, int start, int end) {
 
273
                        Hashtable d = new Hashtable(hashcoder);
 
274
                        for (int index = start; index <= end; index++) {
 
275
                                object element = aCollection[index];
 
276
                                if (d.ContainsKey(element)) {
 
277
                                        List<int> list = (List<int>)d[element];
 
278
                                        list.Add(index);
 
279
                                } else {
 
280
                                        List<int> list = new List<int>();
 
281
                                        list.Add(index);
 
282
                                        d[element] = list;
 
283
                                }
 
284
                        }
 
285
                        foreach (List<int> list in d.Values)
 
286
                                list.Reverse();
 
287
                        return d;
 
288
                }
 
289
 
 
290
                /*
 
291
                # Find the place at which aValue would normally be inserted into the
 
292
                # array. If that place is already occupied by aValue, do nothing, and
 
293
                # return undef. If the place does not exist (i.e., it is off the end of
 
294
                # the array), add it to the end, otherwise replace the element at that
 
295
                # point with aValue.  It is assumed that the array's values are numeric.
 
296
                # This is where the bulk (75%) of the time is spent in this module, so
 
297
                # try to make it fast!
 
298
                */
 
299
                // NOTE: Instead of returning undef, it returns -1.
 
300
                int _replaceNextLargerWith(List<int> array, int value, int high) {
 
301
                        if (high <= 0)
 
302
                                high = array.Count-1;
 
303
                
 
304
                        // off the end?
 
305
                        if (high == -1 || value > (int)array[array.Count-1]) {
 
306
                                array.Add(value);
 
307
                                return array.Count-1;
 
308
                        }
 
309
                
 
310
                        // binary search for insertion point...
 
311
                        int low = 0;
 
312
                        int index, found;
 
313
                        while (low <= high) {
 
314
                                index = (high + low) / 2;
 
315
                
 
316
                                found = (int)array[index];
 
317
                
 
318
                                if (value == found) 
 
319
                                        return -1;
 
320
                                else if (value > found)
 
321
                                        low = index + 1;
 
322
                                else
 
323
                                        high = index - 1;
 
324
                        }
 
325
                
 
326
                        // # now insertion point is in $low.
 
327
                        array[low] = value;    // overwrite next larger
 
328
                        return low;
 
329
                }
 
330
 
 
331
                /*
 
332
                # This method computes the longest common subsequence in $a and $b.
 
333
                
 
334
                # Result is array or ref, whose contents is such that
 
335
                #   $a->[ $i ] == $b->[ $result[ $i ] ]
 
336
                # foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined.
 
337
                
 
338
                # An additional argument may be passed; this is a hash or key generating
 
339
                # function that should return a string that uniquely identifies the given
 
340
                # element.  It should be the case that if the key is the same, the elements
 
341
                # will compare the same. If this parameter is undef or missing, the key
 
342
                # will be the element as a string.
 
343
                
 
344
                # By default, comparisons will use "eq" and elements will be turned into keys
 
345
                # using the default stringizing operator '""'.
 
346
                
 
347
                # Additional parameters, if any, will be passed to the key generation
 
348
                # routine.
 
349
                */
 
350
                
 
351
                bool compare(object a, object b) {
 
352
                        if (comparer == null) return a.Equals(b);
 
353
                        return comparer.Compare(a, b) == 0;
 
354
                }
 
355
                
 
356
                bool IsPrepared(out Hashtable bMatches) {
 
357
                        bMatches = null;
 
358
                        return false;
 
359
                }
 
360
                
 
361
                List<int> _longestCommonSubsequence(IList a, IList b) {
 
362
                        int aStart = 0;
 
363
                        int aFinish = a.Count-1;
 
364
                        List<int> matchVector = new List<int>();
 
365
                        Hashtable bMatches;
 
366
                        
 
367
                        // initialize matchVector to length of a
 
368
                        for (int i = 0; i < a.Count; i++)
 
369
                                matchVector.Add(-1);
 
370
                        
 
371
                        if (!IsPrepared(out bMatches)) {
 
372
                                int bStart = 0;
 
373
                                int bFinish = b.Count-1;
 
374
                
 
375
                                // First we prune off any common elements at the beginning
 
376
                                while (aStart <= aFinish && bStart <= bFinish && compare(a[aStart], b[bStart]))
 
377
                                        matchVector[aStart++] = bStart++;
 
378
                
 
379
                                // now the end
 
380
                                while (aStart <= aFinish && bStart <= bFinish && compare(a[aFinish], b[bFinish]))
 
381
                                        matchVector[aFinish--] = bFinish--;
 
382
                
 
383
                                // Now compute the equivalence classes of positions of elements
 
384
                                bMatches =
 
385
                                  _withPositionsOfInInterval(b, bStart, bFinish);
 
386
                        }
 
387
                        
 
388
                        List<int> thresh = new List<int>();
 
389
                        List<Trio> links = new List<Trio>();
 
390
                
 
391
                        for (int i = aStart; i <= aFinish; i++) {
 
392
                                List<int> aimatches = (List<int>)bMatches[a[i]];
 
393
                                if (aimatches != null) {
 
394
                                        int k = 0;
 
395
                                        for (int ji = 0; ji < aimatches.Count; ji++) {
 
396
                                                int j = aimatches[ji];
 
397
                                                // # optimization: most of the time this will be true
 
398
                                                if (k>0 && (int)thresh[k] > j && (int)thresh[k-1] < j)
 
399
                                                        thresh[k] = j;
 
400
                                                else
 
401
                                                        k = _replaceNextLargerWith(thresh, j, k);
 
402
                
 
403
                                                // oddly, it's faster to always test this (CPU cache?).
 
404
                                                if (k != -1) {
 
405
                                                        Trio t = new Trio( (Trio)( k>0 ? links[k-1] : null ), i, j );
 
406
                                                        if (k == links.Count)
 
407
                                                                links.Add( t );
 
408
                                                        else
 
409
                                                                links[k] = t;
 
410
                                                }
 
411
                                        }
 
412
                                }
 
413
                        }
 
414
                
 
415
                        if (thresh.Count > 0) {
 
416
                                for (Trio link = (Trio)links[thresh.Count-1]; link != null; link = link.a)
 
417
                                        matchVector[link.b] = link.c;
 
418
                        }
 
419
                        
 
420
                        return matchVector;
 
421
                }
 
422
 
 
423
                /*void prepare(IList list) {
 
424
                        prepared = _withPositionsOfInInterval(list, 0, list.Count-1);
 
425
                        preparedlist = list;
 
426
                }*/
 
427
                
 
428
                void LCSidx(IList a, IList b, out List<int> am, out List<int> bm) {
 
429
                        List<int> match = _longestCommonSubsequence(a, b);
 
430
                        am = new List<int>();
 
431
                        for (int i = 0; i < match.Count; i++)
 
432
                                if ((int)match[i] != -1)
 
433
                                        am.Add(i);
 
434
                        bm = new List<int>();
 
435
                        for (int vi = 0; vi < am.Count; vi++)
 
436
                                bm.Add(match[am[vi]]);
 
437
                }
 
438
                
 
439
                List<int> compact_diff(IList a, IList b) {
 
440
                        List<int> am, bm, cdiff;
 
441
                        LCSidx(a, b, out am, out bm);
 
442
                        cdiff = new List<int>();
 
443
                        int ai = 0, bi = 0;
 
444
                        cdiff.Add(ai);
 
445
                        cdiff.Add(bi);
 
446
                        while (true) {
 
447
                                while(am.Count > 0 && ai == (int)am[0] && bi == (int)bm[0]) {
 
448
                                        am.RemoveAt(0);
 
449
                                        bm.RemoveAt(0);
 
450
                                        ++ai;
 
451
                                        ++bi;
 
452
                                }
 
453
                                
 
454
                                cdiff.Add(ai);
 
455
                                cdiff.Add(bi);
 
456
                                if (am.Count == 0) break;
 
457
                                ai = (int)am[0];
 
458
                                bi = (int)bm[0];
 
459
                                cdiff.Add(ai);
 
460
                                cdiff.Add(bi);
 
461
                        }
 
462
 
 
463
                        if (ai < a.Count || bi < b.Count) {
 
464
                                cdiff.Add(a.Count);
 
465
                                cdiff.Add(b.Count);
 
466
                        }
 
467
 
 
468
                        return cdiff;
 
469
                }
 
470
                
 
471
                int _End;
 
472
                bool _Same;
 
473
                List<int> cdif = null;
 
474
                
 
475
                void init() {
 
476
                        cdif = compact_diff(left, right);
 
477
                        _Same = true;
 
478
                        if (0 == (int)cdif[2] && 0 == (int)cdif[3]) {
 
479
                                _Same = false;
 
480
                                cdif.RemoveAt(0);
 
481
                                cdif.RemoveAt(0);
 
482
                        }
 
483
                        
 
484
                        _End = (1+cdif.Count)/2;
 
485
                }
 
486
                
 
487
                private class Enumerator : IEnumerator {
 
488
                        Diff diff;
 
489
                        int _Pos, _Off;
 
490
                        
 
491
                        public Enumerator(Diff diff) {
 
492
                                this.diff = diff;
 
493
                                Reset();
 
494
                        }
 
495
                        
 
496
                        public object Current { get { _ChkPos(); return gethunk(); } }
 
497
                        
 
498
                        public bool MoveNext() { return next(); }
 
499
                        
 
500
                        public void Reset() { reset(0); }
 
501
                        
 
502
                        void _ChkPos() {
 
503
                                if (_Pos == 0) throw new InvalidOperationException("Position is reset.");
 
504
                        }
 
505
                        
 
506
                        void reset(int pos) {
 
507
                                if (pos < 0 || diff._End <= pos) pos = -1;
 
508
                                _Pos = pos;
 
509
                                _Off = 2*pos - 1;
 
510
                        }
 
511
                        
 
512
                        bool next() {
 
513
                                reset(_Pos+1);
 
514
                                return _Pos != -1;
 
515
                        }
 
516
                        
 
517
                        Hunk gethunk() {
 
518
                                _ChkPos();
 
519
                                
 
520
                                int a1, a2, b1, b2;
 
521
                                
 
522
                                int off1 = 1 + _Off;
 
523
                                int off2 = 2 + _Off;
 
524
                                
 
525
                                a1 = (int)diff.cdif[off1-2];
 
526
                                a2 = (int)diff.cdif[off1] - 1;
 
527
                                b1 = (int)diff.cdif[off2-2];
 
528
                                b2 = (int)diff.cdif[off2] - 1;
 
529
                                
 
530
                                bool s = same();
 
531
                                return new Hunk(diff.left, diff.right, a1, a2, b1, b2, s);
 
532
                        }
 
533
                        
 
534
                        bool same() {
 
535
                                _ChkPos();
 
536
                                if (diff._Same != ((1 & _Pos) != 0))
 
537
                                        return false;
 
538
                                return true;
 
539
                        }
 
540
                }
 
541
        }
 
542
        
 
543
        public class Range : IList {
 
544
                IList list;
 
545
                int start, count;
 
546
                
 
547
                static ArrayList EmptyList = new ArrayList();
 
548
                
 
549
                public Range(IList list, int start, int count) {
 
550
                        this.list = list;
 
551
                        this.start = start;
 
552
                        this.count = count;
 
553
                }
 
554
                
 
555
                public int Start { get { return start; } }
 
556
                
 
557
                public int Count { get { return count; } }
 
558
                
 
559
                public int End { get { return start+count-1; } }
 
560
                
 
561
                private void Check() {
 
562
                        if (count > 0 && list == null)
 
563
                                throw new InvalidOperationException("This range does not refer to a list with data.");
 
564
                }
 
565
                
 
566
                public object this[int index] {
 
567
                        get {
 
568
                                Check();
 
569
                                if (index < 0 || index >= count)
 
570
                                        throw new ArgumentException("index");
 
571
                                return list[index+start];
 
572
                        }
 
573
                }
 
574
                
 
575
                // IEnumerable Functions
 
576
 
 
577
                System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
 
578
                        if (count == 0 && list == null) return EmptyList.GetEnumerator();
 
579
                        Check();
 
580
                        return new Enumer(this);
 
581
                }
 
582
                
 
583
                private class Enumer : IEnumerator {
 
584
                        Range list;
 
585
                        int index = -1;
 
586
                        public Enumer(Range list) { this.list = list; }
 
587
                        public void Reset() { index = -1; }
 
588
                        public bool MoveNext() {
 
589
                                index++;
 
590
                                return index < list.Count;
 
591
                        }
 
592
                        public object Current { get { return list[index]; } }
 
593
                }
 
594
                
 
595
                // ICollection Functions
 
596
                
 
597
                void ICollection.CopyTo(Array array, int index) {
 
598
                        Check();
 
599
                        for (int i = 0; i < Count; i++)
 
600
                                array.SetValue(this[i], i + index);
 
601
                }
 
602
                object ICollection.SyncRoot {
 
603
                                get { return null; }
 
604
                        }
 
605
                bool ICollection.IsSynchronized {
 
606
                        get { return false; }
 
607
                }
 
608
                
 
609
                // IList Functions
 
610
                
 
611
                bool IList.IsFixedSize { get { return true; } }
 
612
 
 
613
                bool IList.IsReadOnly { get { return true; } }
 
614
                
 
615
                object IList.this[int index] { get { throw new InvalidOperationException(); } set { throw new InvalidOperationException(); } }
 
616
 
 
617
                int IList.Add(object obj) { throw new InvalidOperationException(); }
 
618
                
 
619
                void IList.Clear() { throw new InvalidOperationException(); }
 
620
                
 
621
                void IList.Insert(int index, object obj) { throw new InvalidOperationException(); }
 
622
                
 
623
                void IList.Remove(object obj) { throw new InvalidOperationException(); }
 
624
                
 
625
                void IList.RemoveAt(int index) { throw new InvalidOperationException(); }
 
626
                
 
627
                public bool Contains(object obj) {
 
628
                        return IndexOf(obj) != -1;
 
629
                }
 
630
                
 
631
                public int IndexOf(object obj) {
 
632
                        for (int i = 0; i < Count; i++)
 
633
                                if (obj.Equals(this[i]))
 
634
                                        return i;
 
635
                        return -1;
 
636
                }
 
637
        }
 
638
 
 
639
}