2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include "NGMerging.h"
25 #import <Foundation/Foundation.h>
26 #import <Foundation/NSObject.h>
28 static NSString *NGCannotMergeWithObjectException =
29 @"NGCannotMergeWithObjectException";
31 @implementation NSObject(NGMerging)
33 - (BOOL)canMergeWithObject:(id)_object {
34 return ((_object == nil) || (_object == self)) ? YES : NO;
37 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
38 return [(id<NSCopying>)self copyWithZone:_zone];
41 - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone {
42 if ((_object == nil) || (_object == self))
43 return [self _makeMergeCopyWithZone:_zone];
45 [NSException raise:NGCannotMergeWithObjectException
46 format:@"cannot merge objects of class %@ and %@",
47 NSStringFromClass([self class]),
48 NSStringFromClass([_object class])];
52 - (id)mergeWithObject:(id)_object {
53 return [self mergeWithObject:_object zone:NULL];
58 @implementation NSDictionary(NGMerging)
60 - (BOOL)canMergeWithObject:(id)_object {
61 if ((self == _object) || (_object == nil))
64 if ([_object isKindOfClass:[NSDictionary class]])
70 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
74 - (id)mergeWithDictionary:(NSDictionary *)_object zone:(NSZone *)_zone {
75 NSMutableDictionary *result;
76 NSArray *aKeys, *bKeys;
79 if ((self == _object) || (_object == nil))
80 return [self _makeMergeCopyWithZone:_zone];
82 aKeys = [self allKeys];
83 bKeys = [_object allKeys];
84 result = [NSMutableDictionary dictionary];
86 /* merge all keys of a */
87 for (i = 0, count = [aKeys count]; i < count; i++) {
91 key = [aKeys objectAtIndex:i];
92 av = [self objectForKey:key];
93 bv = [_object objectForKey:key];
96 /* key is only in a */
97 [result setObject:av forKey:key];
100 /* key is in both - need to merge */
101 if ([av canMergeWithObject:bv]) {
102 av = [av mergeWithObject:bv zone:_zone];
103 [result setObject:av forKey:key];
106 // if objects cannot be merged, av wins
107 [result setObject:av forKey:key];
111 /* add remaining keys in b */
112 for (i = 0, count = [bKeys count]; i < count; i++) {
115 key = [bKeys objectAtIndex:i];
116 if ([result objectForKey:key])
117 // already merged key ..
120 [result setObject:[_object objectForKey:key] forKey:key];
126 - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone {
127 if ((self == _object) || (_object == nil))
128 return [self _makeMergeCopyWithZone:_zone];
130 if ([_object isKindOfClass:[NSDictionary class]])
131 return [self mergeWithDictionary:_object zone:_zone];
133 [NSException raise:NGCannotMergeWithObjectException
134 format:@"cannot merge %@ with %@",
135 NSStringFromClass([self class]),
136 NSStringFromClass([_object class])];
142 @implementation NSMutableDictionary(NGMerging)
144 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
145 return [self copyWithZone:_zone];
150 @implementation NSArray(NGMerging)
152 - (BOOL)canMergeWithObject:(id)_object {
153 if ((self == _object) || (_object == nil))
156 if ([_object respondsToSelector:@selector(objectEnumerator)])
162 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
163 return [self retain];
166 - (id)mergeWithEnumeration:(NSEnumerator *)_object zone:(NSZone *)_zone {
167 NSMutableArray *result;
171 return [self _makeMergeCopyWithZone:_zone];
173 /* make copy of self */
174 result = [[self mutableCopyWithZone:_zone] autorelease];
176 /* add other elements */
177 while ((value = [_object nextObject]))
178 [result addObject:value];
183 - (id)mergeWithArray:(NSArray *)_object zone:(NSZone *)_zone {
185 return [self _makeMergeCopyWithZone:_zone];
187 return [self arrayByAddingObjectsFromArray:_object];
190 - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone {
192 return [self _makeMergeCopyWithZone:_zone];
194 if ([_object respondsToSelector:@selector(objectEnumerator)])
195 return [self mergeWithEnumeration:[_object objectEnumerator] zone:_zone];
197 [NSException raise:NGCannotMergeWithObjectException
198 format:@"cannot merge %@ with %@",
199 NSStringFromClass([self class]),
200 NSStringFromClass([_object class])];
206 @implementation NSMutableArray(NGMerging)
208 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
209 return [self copyWithZone:_zone];
214 // for static linking
216 void __link_NGExtensions_NGMerging(void) {
217 __link_NGExtensions_NGMerging();