2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE 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 SOPE 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 SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include "NGMerging.h"
24 #import <Foundation/Foundation.h>
25 #import <Foundation/NSObject.h>
27 static NSString *NGCannotMergeWithObjectException =
28 @"NGCannotMergeWithObjectException";
30 @implementation NSObject(NGMerging)
32 - (BOOL)canMergeWithObject:(id)_object {
33 return ((_object == nil) || (_object == self)) ? YES : NO;
36 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
37 return [(id<NSCopying>)self copyWithZone:_zone];
40 - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone {
41 if ((_object == nil) || (_object == self))
42 return [self _makeMergeCopyWithZone:_zone];
44 [NSException raise:NGCannotMergeWithObjectException
45 format:@"cannot merge objects of class %@ and %@",
46 NSStringFromClass([self class]),
47 NSStringFromClass([_object class])];
51 - (id)mergeWithObject:(id)_object {
52 return [self mergeWithObject:_object zone:NULL];
57 @implementation NSDictionary(NGMerging)
59 - (BOOL)canMergeWithObject:(id)_object {
60 if ((self == _object) || (_object == nil))
63 if ([_object isKindOfClass:[NSDictionary class]])
69 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
73 - (id)mergeWithDictionary:(NSDictionary *)_object zone:(NSZone *)_zone {
74 NSMutableDictionary *result;
75 NSArray *aKeys, *bKeys;
78 if ((self == _object) || (_object == nil))
79 return [self _makeMergeCopyWithZone:_zone];
81 aKeys = [self allKeys];
82 bKeys = [_object allKeys];
83 result = [NSMutableDictionary dictionary];
85 /* merge all keys of a */
86 for (i = 0, count = [aKeys count]; i < count; i++) {
90 key = [aKeys objectAtIndex:i];
91 av = [self objectForKey:key];
92 bv = [_object objectForKey:key];
95 /* key is only in a */
96 [result setObject:av forKey:key];
99 /* key is in both - need to merge */
100 if ([av canMergeWithObject:bv]) {
101 av = [av mergeWithObject:bv zone:_zone];
102 [result setObject:av forKey:key];
105 // if objects cannot be merged, av wins
106 [result setObject:av forKey:key];
110 /* add remaining keys in b */
111 for (i = 0, count = [bKeys count]; i < count; i++) {
114 key = [bKeys objectAtIndex:i];
115 if ([result objectForKey:key])
116 // already merged key ..
119 [result setObject:[_object objectForKey:key] forKey:key];
125 - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone {
126 if ((self == _object) || (_object == nil))
127 return [self _makeMergeCopyWithZone:_zone];
129 if ([_object isKindOfClass:[NSDictionary class]])
130 return [self mergeWithDictionary:_object zone:_zone];
132 [NSException raise:NGCannotMergeWithObjectException
133 format:@"cannot merge %@ with %@",
134 NSStringFromClass([self class]),
135 NSStringFromClass([_object class])];
141 @implementation NSMutableDictionary(NGMerging)
143 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
144 return [self copyWithZone:_zone];
149 @implementation NSArray(NGMerging)
151 - (BOOL)canMergeWithObject:(id)_object {
152 if ((self == _object) || (_object == nil))
155 if ([_object respondsToSelector:@selector(objectEnumerator)])
161 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
162 return [self retain];
165 - (id)mergeWithEnumeration:(NSEnumerator *)_object zone:(NSZone *)_zone {
166 NSMutableArray *result;
170 return [self _makeMergeCopyWithZone:_zone];
172 /* make copy of self */
173 result = [[self mutableCopyWithZone:_zone] autorelease];
175 /* add other elements */
176 while ((value = [_object nextObject]))
177 [result addObject:value];
182 - (id)mergeWithArray:(NSArray *)_object zone:(NSZone *)_zone {
184 return [self _makeMergeCopyWithZone:_zone];
186 return [self arrayByAddingObjectsFromArray:_object];
189 - (id)mergeWithObject:(id)_object zone:(NSZone *)_zone {
191 return [self _makeMergeCopyWithZone:_zone];
193 if ([_object respondsToSelector:@selector(objectEnumerator)])
194 return [self mergeWithEnumeration:[_object objectEnumerator] zone:_zone];
196 [NSException raise:NGCannotMergeWithObjectException
197 format:@"cannot merge %@ with %@",
198 NSStringFromClass([self class]),
199 NSStringFromClass([_object class])];
205 @implementation NSMutableArray(NGMerging)
207 - (id)_makeMergeCopyWithZone:(NSZone *)_zone {
208 return [self copyWithZone:_zone];
213 // for static linking
215 void __link_NGExtensions_NGMerging(void) {
216 __link_NGExtensions_NGMerging();