/* EOAdaptorChannel.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: October 1996 This file is part of the GNUstep Database Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #import #import #import #import #import #if LIB_FOUNDATION_LIBRARY # include #else # include #endif #include "EORecordDictionary.h" @implementation EORecordDictionary static NSDictionary *emptyDict = nil; - (id)init { RELEASE(self); if (emptyDict == nil) emptyDict = [[NSDictionary alloc] init]; return [emptyDict retain]; } - (id)initWithObjects:(id *)_objects forKeys:(id *)_keys count:(unsigned int)_count { if (_count == 0) { RELEASE(self); if (emptyDict == nil) emptyDict = [[NSDictionary alloc] init]; return [emptyDict retain]; } if (_count == 1) { RELEASE(self); return [[NSDictionary alloc] initWithObjects:_objects forKeys:_keys count:_count]; } self->count = _count; while(_count--) { if ((_keys[_count] == nil) || (_objects[_count] == nil)) { [NSException raise:NSInvalidArgumentException format:@"Nil object to be added in dictionary"]; } self->entries[_count].key = RETAIN(_keys[_count]); self->entries[_count].hash = [_keys[_count] hash]; self->entries[_count].value = RETAIN(_objects[_count]); } return self; } - (id)initWithDictionary:(NSDictionary *)dictionary { // TODO: who calls this method? NSEnumerator *keys; unsigned char i; keys = [dictionary keyEnumerator]; self->count = [dictionary count]; for (i = 0; i < self->count; i++) { id key = [keys nextObject]; self->entries[i].key = RETAIN(key); self->entries[i].hash = [key hash]; self->entries[i].value = RETAIN([dictionary objectForKey:key]); } return self; } - (void)dealloc { /* keys are always NSString keys?! */ #if GNU_RUNTIME static Class LastKeyClass = Nil; static IMP keyRelease = 0; static unsigned misses = 0, hits = 0; #endif register unsigned char i; for (i = 0; i < self->count; i++) { register NSString *key = self->entries[i].key; #if GNU_RUNTIME if (*(id *)key != LastKeyClass) { LastKeyClass = *(id *)key; keyRelease = method_get_imp(class_get_instance_method(LastKeyClass, @selector(release))); misses++; } else hits++; keyRelease(key, NULL /* dangerous? */); #if PROF_METHOD_CACHE if (hits % 1000 == 0 && hits != 0) NSLog(@"%s: DB HITS: %d MISSES: %d", __PRETTY_FUNCTION__,hits, misses); #endif #else [key release]; #endif RELEASE(self->entries[i].value); } [super dealloc]; } /* operations */ - (id)objectForKey:(id)aKey { register EORecordDictionaryEntry *e = self->entries; register signed char i; register unsigned hash; #if GNU_RUNTIME static Class LastKeyClass = Nil; static unsigned (*keyHash)(id,SEL) = 0; static BOOL (*keyEq)(id,SEL,id) = 0; #if PROF_METHOD_CACHE static unsigned misses = 0, hits = 0; #endif #endif #if GNU_RUNTIME if (aKey == nil) return nil; if (*(id *)aKey != LastKeyClass) { LastKeyClass = *(id *)aKey; keyHash = (void *) method_get_imp(class_get_instance_method(LastKeyClass, @selector(hash))); keyEq = (void *) method_get_imp(class_get_instance_method(LastKeyClass, @selector(isEqual:))); } hash = keyHash(aKey, NULL /* dangerous? */); #else hash = [aKey hash]; #endif for (i = (self->count - 1); i >= 0; i--, e++) { if (e->hash != hash) continue; if (e->key == aKey) return e->value; #if GNU_RUNTIME if (keyEq(e->key, NULL /* dangerous? */, aKey)) return e->value; #else if ([e->key isEqual:aKey]) return e->value; #endif } return nil; } - (unsigned int)count { return self->count; } - (BOOL)isNotEmpty { return self->count > 0 ? YES : NO; } - (NSEnumerator *)keyEnumerator { return [[[_EORecordDictionaryKeyEnumerator alloc] initWithDictionary:self firstEntry:self->entries count:self->count] autorelease]; } @end /* NSConcreteSmallDictionary */ @implementation _EORecordDictionaryKeyEnumerator - (id)initWithDictionary:(EORecordDictionary *)_dict firstEntry:(EORecordDictionaryEntry *)_firstEntry count:(unsigned char)_count { self->dict = RETAIN(_dict); self->currentEntry = _firstEntry; self->count = _count; return self; } - (void)dealloc { RELEASE(self->dict); [super dealloc]; } - (id)nextObject { if (self->count > 0) { id obj; obj = self->currentEntry->key; self->currentEntry++; self->count--; return obj; } return nil; } @end /* _NSConcreteSmallDictionaryKeyEnumerator */