mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-25 09:41:15 +00:00
objects and NeXT-compatibility. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@947 72102866-910b-0410-8b05-ffd578937521
210 lines
4.3 KiB
Objective-C
210 lines
4.3 KiB
Objective-C
/* Implementation for Objective-C Bag collection object
|
|
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
|
|
|
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
|
Created: May 1993
|
|
|
|
This file is part of the GNU Objective C Class 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; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <objects/Bag.h>
|
|
#include <objects/CollectionPrivate.h>
|
|
|
|
#define DEFAULT_BAG_CAPACITY 32
|
|
|
|
@implementation Bag
|
|
|
|
// MANAGING CAPACITY;
|
|
|
|
/* Eventually we will want to have better capacity management,
|
|
potentially keep default capacity as a class variable. */
|
|
|
|
+ (unsigned) defaultCapacity
|
|
{
|
|
return DEFAULT_BAG_CAPACITY;
|
|
}
|
|
|
|
// INITIALIZING AND FREEING;
|
|
|
|
/* This is the designated initializer of this class */
|
|
/* Override designated initializer of superclass */
|
|
- initWithCapacity: (unsigned)cap
|
|
{
|
|
_contents_map = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
|
NSIntMapValueCallBacks,
|
|
cap);
|
|
_count = 0;
|
|
return self;
|
|
}
|
|
|
|
/* Override Collection's designated initializer */
|
|
- initWithObjects: (id*)objs count: (unsigned)count
|
|
{
|
|
[self initWithCapacity: count];
|
|
while (count--)
|
|
[self addObject: objs[count]];
|
|
return self;
|
|
}
|
|
|
|
|
|
/* Archiving must mimic the above designated initializer */
|
|
|
|
/* Archiving must mimic the above designated initializer */
|
|
|
|
- (void) encodeWithCoder: anEncoder
|
|
{
|
|
[self notImplemented:_cmd];
|
|
}
|
|
|
|
- initWithCoder: aDecoder
|
|
{
|
|
[self notImplemented:_cmd];
|
|
return self;
|
|
}
|
|
|
|
/* Empty copy must empty an allocCopy'ed version of self */
|
|
- emptyCopy
|
|
{
|
|
Bag *copy = [super emptyCopy];
|
|
copy->_contents_map = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
|
NSIntMapValueCallBacks,
|
|
0);
|
|
copy->_count = 0;
|
|
return copy;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
NSFreeMapTable (_contents_map);
|
|
[super _collectionDealloc];
|
|
}
|
|
|
|
/* This must work without sending any messages to content objects */
|
|
- (void) _collectionEmpty
|
|
{
|
|
NSResetMapTable (_contents_map);
|
|
_count = 0;
|
|
}
|
|
|
|
// ADDING;
|
|
|
|
- (void) addObject: newObject withOccurrences: (unsigned)count
|
|
{
|
|
unsigned new_count = (unsigned) NSMapGet (_contents_map, newObject);
|
|
new_count += count;
|
|
NSMapInsert (_contents_map, newObject, (void*)new_count);
|
|
_count += count;
|
|
}
|
|
|
|
- (void) addObject: newObject
|
|
{
|
|
[self addObject: newObject withOccurrences: 1];
|
|
}
|
|
|
|
|
|
// REMOVING AND REPLACING;
|
|
|
|
- (void) removeObject: oldObject occurrences: (unsigned)count
|
|
{
|
|
unsigned c = (unsigned) NSMapGet (_contents_map, oldObject);
|
|
if (c)
|
|
{
|
|
if (c <= count)
|
|
{
|
|
NSMapRemove (_contents_map, oldObject);
|
|
_count -= c;
|
|
}
|
|
else
|
|
{
|
|
NSMapInsert (_contents_map, oldObject, (void*)(c - count));
|
|
_count -= count;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) removeObject: oldObject
|
|
{
|
|
[self removeObject: oldObject occurrences:1];
|
|
}
|
|
|
|
- (void) uniqueContents
|
|
{
|
|
[self notImplemented: _cmd];
|
|
}
|
|
|
|
|
|
// TESTING;
|
|
|
|
- (unsigned) count
|
|
{
|
|
return _count;
|
|
}
|
|
|
|
- (unsigned) uniqueCount
|
|
{
|
|
return NSCountMapTable (_contents_map);
|
|
}
|
|
|
|
- (unsigned) occurrencesOfObject: anObject
|
|
{
|
|
return (unsigned) NSMapGet (_contents_map, anObject);
|
|
}
|
|
|
|
|
|
// ENUMERATING;
|
|
|
|
struct BagEnumState
|
|
{
|
|
NSMapEnumerator me;
|
|
id object;
|
|
unsigned count;
|
|
};
|
|
|
|
#define ES ((struct BagEnumState *) *enumState)
|
|
|
|
- nextObjectWithEnumState: (void**)enumState
|
|
{
|
|
if (!(ES->count))
|
|
if (!NSNextMapEnumeratorPair (&(ES->me),
|
|
(void**) &(ES->object),
|
|
(void**) &(ES->count)))
|
|
return NO_OBJECT;
|
|
ES->count--;
|
|
return ES->object;
|
|
}
|
|
|
|
- (void*) newEnumState
|
|
{
|
|
/* init for start of enumeration. */
|
|
void *vp;
|
|
void **enumState = &vp;
|
|
OBJC_MALLOC(*enumState, struct BagEnumState, 1);
|
|
ES->me = NSEnumerateMapTable (_contents_map);
|
|
ES->object = nil;
|
|
ES->count = 0;
|
|
return vp;
|
|
}
|
|
|
|
- (void) freeEnumState: (void**)enumState
|
|
{
|
|
if (*enumState)
|
|
OBJC_FREE(*enumState);
|
|
}
|
|
|
|
@end
|
|
|
|
|