1//
2//  OrderedDictionary.m
3//  OrderedDictionary
4//
5//  Modified version (Added indexForKey/Value functions)
6//
7//  Created by Matt Gallagher on 19/12/08.
8//  Copyright 2008 Matt Gallagher. All rights reserved.
9//
10//  This software is provided 'as-is', without any express or implied
11//  warranty. In no event will the authors be held liable for any damages
12//  arising from the use of this software. Permission is granted to anyone to
13//  use this software for any purpose, including commercial applications, and to
14//  alter it and redistribute it freely, subject to the following restrictions:
15//
16//  1. The origin of this software must not be misrepresented; you must not
17//     claim that you wrote the original software. If you use this software
18//     in a product, an acknowledgment in the product documentation would be
19//     appreciated but is not required.
20//  2. Altered source versions must be plainly marked as such, and must not be
21//     misrepresented as being the original software.
22//  3. This notice may not be removed or altered from any source
23//     distribution.
24//
25
26#import "OrderedDictionary.h"
27
28NSString *DescriptionForObject(NSObject *object, id locale, NSUInteger indent)
29{
30	NSString *objectString;
31	if ([object isKindOfClass:[NSString class]])
32	{
33		objectString = (NSString *)[[object retain] autorelease];
34	}
35	else if ([object respondsToSelector:@selector(descriptionWithLocale:indent:)])
36	{
37		objectString = [(NSDictionary *)object descriptionWithLocale:locale indent:indent];
38	}
39	else if ([object respondsToSelector:@selector(descriptionWithLocale:)])
40	{
41		objectString = [(NSSet *)object descriptionWithLocale:locale];
42	}
43	else
44	{
45		objectString = [object description];
46	}
47	return objectString;
48}
49
50@implementation OrderedDictionary
51
52- (id)init
53{
54	return [self initWithCapacity:0];
55}
56
57- (id)initWithCapacity:(NSUInteger)capacity
58{
59	self = [super init];
60	if (self != nil)
61	{
62		dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
63		array = [[NSMutableArray alloc] initWithCapacity:capacity];
64	}
65	return self;
66}
67
68- (void)dealloc
69{
70	[dictionary release];
71	[array release];
72	[super dealloc];
73}
74
75- (id)copy
76{
77	return [self mutableCopy];
78}
79
80- (void)setObject:(id)anObject forKey:(id)aKey
81{
82	if (![dictionary objectForKey:aKey])
83	{
84		[array addObject:aKey];
85	}
86	[dictionary setObject:anObject forKey:aKey];
87}
88
89- (void)removeObjectForKey:(id)aKey
90{
91	[dictionary removeObjectForKey:aKey];
92	[array removeObject:aKey];
93}
94
95- (NSUInteger)count
96{
97	return [dictionary count];
98}
99
100- (id)objectForKey:(id)aKey
101{
102	return [dictionary objectForKey:aKey];
103}
104
105- (NSEnumerator *)keyEnumerator
106{
107	return [array objectEnumerator];
108}
109
110- (NSEnumerator *)reverseKeyEnumerator
111{
112	return [array reverseObjectEnumerator];
113}
114
115- (void)insertObject:(id)anObject forKey:(id)aKey atIndex:(NSUInteger)anIndex
116{
117	if ([dictionary objectForKey:aKey])
118	{
119		[self removeObjectForKey:aKey];
120	}
121	[array insertObject:aKey atIndex:anIndex];
122	[dictionary setObject:anObject forKey:aKey];
123}
124
125- (id)keyAtIndex:(NSUInteger)anIndex
126{
127	return [array objectAtIndex:anIndex];
128}
129
130- (NSUInteger)indexForKey:(id)key
131{
132	return [array indexOfObject:key];
133}
134
135- (NSUInteger)indexForValue:(id)value
136{
137	NSArray *keys = [self allKeysForObject:value];
138	if ([keys count] > 0)
139	{
140		return [self indexForKey:[keys objectAtIndex:0]];
141	}
142
143	return NSNotFound;
144}
145
146- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
147{
148	NSMutableString *indentString = [NSMutableString string];
149	NSUInteger i, count = level;
150	for (i = 0; i < count; i++)
151	{
152		[indentString appendFormat:@"    "];
153	}
154
155	NSMutableString *description = [NSMutableString string];
156	[description appendFormat:@"%@{\n", indentString];
157	for (NSObject *key in self)
158	{
159		[description appendFormat:@"%@    %@ = %@;\n", indentString,
160		                          DescriptionForObject(key, locale, level),
161		                          DescriptionForObject([self objectForKey:key], locale, level)];
162	}
163	[description appendFormat:@"%@}\n", indentString];
164	return description;
165}
166
167@end
168