forked from gnachman/iTerm2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
EquivalenceClassSet.m
112 lines (100 loc) · 2.89 KB
/
EquivalenceClassSet.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// TOMORROW: test that everything with affinities works.
//
// EquivalenceClassSet.m
// iTerm
//
// Created by George Nachman on 12/28/11.
// Copyright (c) 2011 Georgetech. All rights reserved.
//
#import "EquivalenceClassSet.h"
@implementation EquivalenceClassSet
- (id)init
{
self = [super init];
if (self) {
index_ = [[NSMutableDictionary alloc] init];
classes_ = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)dealloc
{
[index_ release];
[classes_ release];
[super dealloc];
}
- (NSArray *)valuesEqualTo:(NSObject *)target
{
NSNumber *ec = [index_ objectForKey:target];
return ec ? [classes_ objectForKey:ec] : nil;
}
- (void)addValue:(NSObject *)value toClass:(NSNumber *)ec
{
[self removeValue:value];
[index_ setObject:ec forKey:value];
NSMutableSet *theSet = [classes_ objectForKey:ec];
if (!theSet) {
theSet = [NSMutableSet set];
[classes_ setObject:theSet forKey:ec];
}
[theSet addObject:value];
}
- (NSNumber *)newEquivalenceClass
{
int i = 0;
while ([classes_ objectForKey:[NSNumber numberWithInt:i]]) {
i++;
}
return [NSNumber numberWithInt:i];
}
- (void)setValue:(NSObject *)n1 equalToValue:(NSObject *)n2
{
NSNumber *n1Class = [index_ objectForKey:n1];
NSNumber *n2Class = [index_ objectForKey:n2];
if (n1Class) {
if (n2Class) {
if ([n1Class intValue] != [n2Class intValue]) {
// Merge the equivalence classes. Move every value in n2's class
// (including n2, of course) into n1's.
for (NSNumber *n in [[[classes_ objectForKey:n2Class] copy] autorelease]) {
[self addValue:n toClass:n1Class];
}
}
} else {
// n2 does not belong to an existing equiv class yet so add it to n1's class
[self addValue:n2 toClass:n1Class];
}
} else {
// n1 does not have an equiv relation yet
if (n2Class) {
// n2 has an equiv relation already so add n1 to it
[self addValue:n1 toClass:n2Class];
} else {
// Neither n1 nor n2 has an existing relation so create a new equivalence class
NSNumber *ec = [self newEquivalenceClass];
[self addValue:n2 toClass:ec];
[self addValue:n1 toClass:ec];
}
}
}
- (void)removeValue:(NSObject *)target
{
NSNumber *ec = [index_ objectForKey:target];
if (!ec) {
return;
}
NSMutableSet *c = [classes_ objectForKey:ec];
[c removeObject:target];
[index_ removeObjectForKey:target];
if (!c.count) {
[classes_ removeObjectForKey:ec];
} else if (c.count == 1) {
// An equivalence class with one object is silly so remove its last element.
[self removeValue:[[c allObjects] lastObject]];
}
}
- (NSArray *)classes
{
return [classes_ allValues];
}
@end