]> err.no Git - sope/blob - sope-gdl1/GDLAccess/EORecordDictionary.m
fixed build with gstep-make 1.9.2
[sope] / sope-gdl1 / GDLAccess / EORecordDictionary.m
1 /* 
2    EOAdaptorChannel.m
3
4    Copyright (C) 1996 Free Software Foundation, Inc.
5
6    Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
7    Date: October 1996
8
9    This file is part of the GNUstep Database Library.
10
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Library General Public
13    License as published by the Free Software Foundation; either
14    version 2 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Library General Public License for more details.
20
21    You should have received a copy of the GNU Library General Public
22    License along with this library; see the file COPYING.LIB.
23    If not, write to the Free Software Foundation,
24    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26 // $Id: EORecordDictionary.m 1 2004-08-20 10:38:46Z znek $
27
28 #include <stdarg.h>
29 #include <math.h>
30
31 #import <Foundation/NSObject.h>
32 #import <Foundation/NSDictionary.h>
33 #import <Foundation/NSArray.h>
34 #import <Foundation/NSString.h>
35 #import <Foundation/NSException.h>
36
37 #if LIB_FOUNDATION_LIBRARY
38 #  include <Foundation/exceptions/GeneralExceptions.h>
39 #  include <extensions/objc-runtime.h>
40 #else
41 #  include <NGExtensions/NGObjectMacros.h>
42 #endif
43
44 #include "EORecordDictionary.h"
45
46 @implementation EORecordDictionary
47
48 static NSDictionary *emptyDict = nil;
49
50 - (id)init  {
51   RELEASE(self);
52   if (emptyDict == nil) emptyDict = [[NSDictionary alloc] init];
53   return [emptyDict retain];
54 }
55
56 - (id)initWithObjects:(id *)_objects forKeys:(id *)_keys 
57   count:(unsigned int)_count
58 {
59   if (_count == 0) {
60         RELEASE(self);
61         if (emptyDict == nil) emptyDict = [[NSDictionary alloc] init];
62         return [emptyDict retain];
63   }
64   
65   if (_count == 1) {
66         RELEASE(self);
67         return [[NSDictionary alloc]
68                               initWithObjects:_objects forKeys:_keys
69                               count:_count];
70   }
71   
72   self->count = _count;
73   while(_count--) {
74         if ((_keys[_count] == nil) || (_objects[_count] == nil)) {
75           [NSException raise:NSInvalidArgumentException
76                        format:@"Nil object to be added in dictionary"];
77         }
78         self->entries[_count].key   = RETAIN(_keys[_count]);
79         self->entries[_count].hash  = [_keys[_count] hash];
80         self->entries[_count].value = RETAIN(_objects[_count]);
81   }
82   return self;
83 }
84
85 - (id)initWithDictionary:(NSDictionary *)dictionary {
86   // TODO: who calls this method?
87   NSEnumerator  *keys;
88   unsigned char i;
89     
90   keys = [dictionary keyEnumerator];
91   self->count = [dictionary count];
92
93   for (i = 0; i < self->count; i++) {
94     id key = [keys nextObject];
95     
96     self->entries[i].key   = RETAIN(key);
97     self->entries[i].hash  = [key hash];
98     self->entries[i].value = RETAIN([dictionary objectForKey:key]);
99   }
100   return self;
101 }
102
103 - (void)dealloc {
104   /* keys are always NSString keys?! */
105 #if GNU_RUNTIME
106   static Class LastKeyClass = Nil;
107   static IMP   keyRelease   = 0;
108   static unsigned misses = 0, hits = 0;
109 #endif
110   register unsigned char i;
111     
112   for (i = 0; i < self->count; i++) {
113       register NSString *key = self->entries[i].key;
114 #if GNU_RUNTIME      
115       if (*(id *)key != LastKeyClass) {
116         LastKeyClass = *(id *)key;
117         keyRelease = 
118           method_get_imp(class_get_instance_method(LastKeyClass, 
119                                                    @selector(release)));
120         misses++;
121       }
122       else
123         hits++;
124       
125       keyRelease(key, NULL /* dangerous? */);
126
127 #if PROF_METHOD_CACHE
128       if (hits % 1000 == 0 && hits != 0)
129         NSLog(@"%s: DB HITS: %d MISSES: %d", __PRETTY_FUNCTION__,hits, misses);
130 #endif
131 #else
132       [key release];
133 #endif
134
135       RELEASE(self->entries[i].value);
136   }
137   [super dealloc];
138 }
139
140 /* operations */
141
142 - (id)objectForKey:(id)aKey {
143   register EORecordDictionaryEntry *e = self->entries;
144   register signed char i;
145   register unsigned hash;
146 #if GNU_RUNTIME
147   static Class LastKeyClass = Nil;
148   static unsigned (*keyHash)(id,SEL)  = 0;
149   static BOOL     (*keyEq)(id,SEL,id) = 0;
150 #if PROF_METHOD_CACHE
151   static unsigned misses = 0, hits = 0;
152 #endif
153 #endif
154   
155 #if GNU_RUNTIME      
156   if (aKey == nil)
157     return nil;
158   
159   if (*(id *)aKey != LastKeyClass) {
160     LastKeyClass = *(id *)aKey;
161     keyHash = (void *)
162       method_get_imp(class_get_instance_method(LastKeyClass, 
163                                                @selector(hash)));
164     keyEq = (void *)
165       method_get_imp(class_get_instance_method(LastKeyClass, 
166                                                @selector(isEqual:)));
167   }
168   
169   hash = keyHash(aKey, NULL /* dangerous? */);
170 #else  
171   hash = [aKey hash];
172 #endif
173
174   for (i = (self->count - 1); i >= 0; i--, e++) {
175     if (e->hash != hash)
176       continue;
177     if (e->key == aKey)
178       return e->value;
179     
180 #if GNU_RUNTIME
181     if (keyEq(e->key, NULL /* dangerous? */, aKey))
182       return e->value;
183 #else
184     if ([e->key isEqual:aKey]) 
185       return e->value;
186 #endif
187   }
188   return nil;
189 }
190
191 - (unsigned int)count {
192   return self->count;
193 }
194 - (NSEnumerator *)keyEnumerator {
195   return AUTORELEASE([[_EORecordDictionaryKeyEnumerator alloc]
196                             initWithDictionary:self
197                             firstEntry:self->entries count:self->count]);
198 }
199
200 @end /* NSConcreteSmallDictionary */
201
202 @implementation _EORecordDictionaryKeyEnumerator
203
204 - (id)initWithDictionary:(EORecordDictionary *)_dict
205   firstEntry:(EORecordDictionaryEntry *)_firstEntry
206   count:(unsigned char)_count
207 {
208     self->dict         = RETAIN(_dict);
209     self->currentEntry = _firstEntry;
210     self->count        = _count;
211     return self;
212 }
213
214 - (void)dealloc {
215     RELEASE(self->dict);
216     [super dealloc];
217 }
218
219 - (id)nextObject {
220   if (self->count > 0) {
221         id obj;
222         obj = self->currentEntry->key;
223         self->currentEntry++;
224         self->count--;
225         return obj;
226   }
227     
228   return nil;
229 }
230
231 @end /* _NSConcreteSmallDictionaryKeyEnumerator */