1
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections;
21
using System.Collections.Generic;
22
using System.Collections.ObjectModel;
24
using System.Runtime.CompilerServices;
26
using ICSharpCode.NRefactory.Utils;
28
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
31
/// Simple interning provider.
33
public sealed class SimpleInterningProvider : InterningProvider
35
sealed class InterningComparer : IEqualityComparer<ISupportsInterning>
37
public bool Equals(ISupportsInterning x, ISupportsInterning y)
39
return x.EqualsForInterning(y);
42
public int GetHashCode(ISupportsInterning obj)
44
return obj.GetHashCodeForInterning();
48
sealed class ListComparer : IEqualityComparer<IEnumerable>
50
public bool Equals(IEnumerable a, IEnumerable b)
52
if (a.GetType() != b.GetType())
54
IEnumerator e1 = a.GetEnumerator();
55
IEnumerator e2 = b.GetEnumerator();
56
while (e1.MoveNext()) {
57
// e1 has more elements than e2; or elements are different
58
if (!e2.MoveNext() || e1.Current != e2.Current)
61
if (e2.MoveNext()) // e2 has more elements than e1
63
// No need to dispose e1/e2: non-generic IEnumerator doesn't implement IDisposable,
64
// and the underlying enumerator will likely be a List<T>.Enumerator which has an empty Dispose() method.
68
public int GetHashCode(IEnumerable obj)
70
int hashCode = obj.GetType().GetHashCode();
72
foreach (object o in obj) {
74
hashCode += RuntimeHelpers.GetHashCode(o);
81
Dictionary<object, object> byValueDict = new Dictionary<object, object>();
82
Dictionary<ISupportsInterning, ISupportsInterning> supportsInternDict = new Dictionary<ISupportsInterning, ISupportsInterning>(new InterningComparer());
83
Dictionary<IEnumerable, IEnumerable> listDict = new Dictionary<IEnumerable, IEnumerable>(new ListComparer());
85
public override ISupportsInterning Intern(ISupportsInterning obj)
90
// ensure objects are frozen when we put them into the dictionary
91
// note that Freeze may change the hash code of the object
92
FreezableHelper.Freeze(obj);
94
ISupportsInterning output;
95
if (supportsInternDict.TryGetValue(obj, out output)) {
98
supportsInternDict.Add(obj, obj);
103
public override string Intern(string text)
109
if (byValueDict.TryGetValue(text, out output))
110
return (string)output;
115
public override object InternValue(object obj)
121
if (byValueDict.TryGetValue(obj, out output))
127
public override IList<T> InternList<T>(IList<T> list)
132
return EmptyList<T>.Instance;
133
if (!list.IsReadOnly)
134
list = new ReadOnlyCollection<T>(list);
136
if (listDict.TryGetValue(list, out output))
137
list = (IList<T>)output;
139
listDict.Add(list, list);