This is IndexedCollection.m in view mode; [Download] [Up]
/* Implementation for Objective-C IndexedCollection object
Copyright (C) 1993 R. Andrew McCallum <mccallum@cs.rochester.edu>
Dept. of Computer Science, U. of Rochester, Rochester, NY 14627
This file is part of the GNU Objective-C Collection 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 <coll/IndexedCollection.h>
#include <coll/IndexedCollectionPrivate.h>
#include <objc/objc-api.h>
@implementation IndexedCollection
+ initialize
{
if (self == [IndexedCollection class])
[self setVersion:-1]; /* alpha release */
return self;
}
/* This is the designated initializer of this class */
- initDescription: (const char *)description
{
[super initDescription:description keyDescription:"I"];
return self;
}
/* Override the designated initializer for our superclass KeyedCollection
to make sure we have unsigned int keys. */
- initDescription: (const char *)contentType
keyDescription: (const char *)keyType
{
if (*keyType != _C_UINT)
[self error:"IndexedCollection key must be an unsigned integer."];
return [self initDescription:contentType];
}
// ADDING;
- insertElement: (elt)newElement atIndex: (unsigned)index
{
return [self subclassResponsibility:_cmd];
}
- insertObject: newObject atIndex: (unsigned)index
{
return [self insertElement:newObject atIndex:index];
}
- insertElement: (elt)newElement before: (elt)oldElement
{
unsigned index = [self indexOfElement:oldElement];
if (index == COLL_NO_INDEX)
return nil;
[self insertElement:newElement atIndex:index];
return self;
}
- insertObject: newObject before: oldObject
{
return [self insertElement:newObject before:oldObject];
}
- insertElement: (elt)newElement after: (elt)oldElement
{
unsigned index = [self indexOfElement:oldElement];
if (index == COLL_NO_INDEX)
return nil;
[self insertElement:newElement atIndex:index+1];
return self;
}
- insertObject: newObject after: oldObject
{
return [self insertElement:newObject after:oldObject];
}
/* Possibly inefficient. Should be overridden. */
- appendElement: (elt)newElement
{
return [self insertElement:newElement atIndex:[self count]];
}
- appendObject: newObject
{
return [self appendElement:newObject];
}
/* Possibly inefficient. Should be overridden. */
- prependElement: (elt)newElement
{
return [self insertElement:newElement atIndex:0];
}
- prependObject: newObject
{
return [self prependElement:newObject];
}
- appendContentsOf: (id <Collecting>) aCollection
{
void doIt(elt e)
{
[self appendElement:e];
}
if (aCollection == self)
[[[self shallowCopy] withElementsCall:doIt] free];
else
[aCollection withElementsCall:doIt];
return self;
}
- prependContentsOf: (id <Collecting>) aCollection
{
void doIt(elt e)
{
/* could use objc_msg_lookup here */
[self prependElement:e];
}
if (aCollection == self)
[[[self shallowCopy] withElementsInReverseCall:doIt] free];
else
{
/* Can I assume that all Collections will inherit from Object? */
if ([(Object*)aCollection
respondsTo:@selector(withElementsInReverseCall:)])
[(id <IndexedCollecting>)aCollection withElementsInReverseCall:doIt];
else
[aCollection withElementsCall:doIt];
}
return self;
}
/* We can not implement this <Collecting> protocol method */
- addElement: (elt)newElement
{
return [self appendElement:newElement];
}
// REPLACING;
/* Subclasses may require different ordering semantics */
- (elt) replaceElement: (elt)oldElement with: (elt)newElement
{
unsigned index = [self indexOfElement:oldElement];
if (index == COLL_NO_INDEX)
return nil;
return [self replaceElementAtIndex:index with:newElement];
}
/* Inefficient. Should be overridden */
- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement
{
elt ret;
ret = [self removeElementAtIndex:index];
[self insertElement:newElement atIndex:index];
return ret;
}
- replaceObjectAtIndex: (unsigned)index with: newObject
{
return [self replaceElementAtIndex:index with:newObject].id_t;
}
// SWAPPING;
/* Perhaps inefficient. May be overridden. */
- swapAtIndeces: (unsigned)index1 : (unsigned)index2
{
elt tmp = [self elementAtIndex:index1];
[self replaceElementAtIndex:index1 with:[self elementAtIndex:index2]];
[self replaceElementAtIndex:index2 with:tmp];
return self;
}
// REMOVING;
- (elt) removeElementAtIndex: (unsigned)index
{
return [self subclassResponsibility:_cmd];
}
- removeObjectAtIndex: (unsigned)index
{
return [self removeElementAtIndex:index].id_t;
}
- (elt) removeFirstElement
{
return [self removeElementAtIndex:0];
}
- removeFirstObject
{
return [self removeFirstElement].id_t;
}
- (elt) removeLastElement
{
return [self removeElementAtIndex:[self count]-1];
}
- removeLastObject
{
return [self removeLastElement].id_t;
}
/* We can not implement this <Collecting> protocol method */
- (elt) removeElement: (elt)oldElement
{
unsigned index = [self indexOfElement:oldElement];
/* This should be object-not-found warning */
if (index == COLL_NO_INDEX)
return COLL_NO_ELEMENT;
return [self removeElementAtIndex:index];
}
// GETTING MEMBERS BY INDEX;
- (elt) elementAtIndex: (unsigned)index
{
return [self subclassResponsibility:_cmd];
}
- objectAtIndex: (unsigned)index
{
return [self elementAtIndex:index].id_t;
}
- (elt) firstElement
{
return [self elementAtIndex:0];
}
- firstObject
{
return [self firstElement].id_t;
}
- (elt) lastElement
{
return [self elementAtIndex:[self count]-1];
}
- lastObject
{
return [self lastElement].id_t;
}
// GETTING INDICES BY ELEMENT;
/* Possibly inefficient. */
- (unsigned) indexOfElement: (elt)anElement
{
unsigned index = 0;
BOOL flag = YES;
void doIt(elt e)
{
if (_compare_func(anElement.void_ptr_t, e.void_ptr_t))
flag = NO;
else
index++;
}
[self withElementsCall:doIt whileTrue:&flag];
if (flag)
{
index = COLL_NO_INDEX;
[self errorElementNotFound:anElement inMethod:_cmd];
}
return index;
}
- (unsigned) indexOfObject: anObject
{
return [self indexOfElement:anObject];
}
// TESTING;
- (BOOL) includesIndex: (unsigned)index
{
if (index < [self count])
return YES;
else
return NO;
}
- (BOOL) includesSameContentsInOrder: (id <IndexedCollecting>)anIndexedColl
{
elt e1, e2;
void *s1, *s2;
if ([self count] != [anIndexedColl count])
return NO;
s1 = s2 = 0;
while ([self getNextElement:&e1 withEnumState:&s1]
&& [anIndexedColl getNextElement:&e2 withEnumState:&s2])
{
if (!_compare_func(e1.void_ptr_t, e2.void_ptr_t))
return NO;
}
return YES;
}
/* is this what we want? */
- (BOOL) isEqual: anObject
{
if ([anObject class] != [self class] &&
[self includesSameContentsInOrder:anObject])
return YES;
else
return NO;
}
// COPYING;
- shallowCopyFrom: (unsigned)start to: (unsigned)stop
{
id newColl = [self emptyCopyAs:[self species]];
unsigned i, myCount = [self count];
for (i = start; i <= stop && i < myCount; i++)
[newColl addElement:[self elementAtIndex:i]];
return newColl;
}
- shallowCopyReplaceFrom: (unsigned)start to: (unsigned)stop
with: (id <Collecting>)replaceCollection
{
id newColl = [self emptyCopyAs:[self species]];
unsigned i, myCount = [self count];
for (i = 0; i < start && i < myCount; i++)
[newColl appendElement:[self elementAtIndex:i]];
[newColl appendContentsOf:replaceCollection];
for (i = stop+1; i < myCount; i++)
[newColl appendElement:[self elementAtIndex:i]];
return newColl;
}
- shallowCopyReplaceFrom: (unsigned)start to: (unsigned)stop
using: (id <Collecting>)replaceCollection
{
id newColl = [self shallowCopy];
unsigned index = start;
BOOL cont = YES;
void doIt (elt e)
{
[newColl replaceElementAtIndex: index with: e];
cont = (index++ != stop);
}
[replaceCollection withElementsCall: doIt whileTrue: &cont];
return newColl;
}
- shallowCopyInReverseAs: aCollectionClass
{
id newColl = [self emptyCopyAs:aCollectionClass];
void doIt(elt e)
{
[newColl appendElement:e];
}
[self withElementsInReverseCall:doIt];
return self;
}
// ENUMERATING;
- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr
withEnumState: (void**)enumState
{
/* (unsigned)*enumState is the index of the element that will be returned */
if (((unsigned)(*enumState)) > [self count]-1)
return NO;
*anElementPtr = [self elementAtIndex:((unsigned)*enumState)];
*aKeyPtr = ((unsigned)*enumState);
((unsigned)(*enumState))++;
return YES;
}
- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState
{
/* (unsigned)*enumState is the index of the element that will be returned */
if (((unsigned)(*enumState)) > [self count]-1)
return NO;
*anElementPtr = [self elementAtIndex:((unsigned)*enumState)];
((unsigned)(*enumState))++;
return YES;
}
- (BOOL) getPrevElement:(elt *)anElementPtr withEnumState: (void**)enumState
{
/* (unsigned)*enumState-1 is the index of the element
that will be returned */
if (!(*enumState))
(unsigned)(*enumState) = [self count]-1;
else
((unsigned)(*enumState))--;
*anElementPtr = [self elementAtIndex:((unsigned)(*enumState))];
return YES;
}
- prevObject: (void**)enumState
{
elt o;
if ([self getPrevElement:&o withEnumState:enumState])
return o.id_t;
else
return COLL_NO_OBJECT;
}
- withElementsInReverseCall: (void(*)(elt))aFunc;
{
BOOL flag = NO;
[self withElementsInReverseCall:aFunc whileTrue:&flag];
return self;
}
- withObjectsInReverseCall: (void(*)(id))aFunc
{
void doIt(elt e)
{
aFunc(e.id_t);
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
return [self withElementsInReverseCall:doIt];
}
- withElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag
{
unsigned i;
for (i = [self count]-1; *flag && i >= 0; i--)
aFunc([self elementAtIndex:i]);
return self;
}
- withObjectsInReverseCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag
{
void doIt(elt e)
{
aFunc(e.id_t);
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
return [self withElementsInReverseCall:doIt whileTrue:flag];
}
- withObjectsInReversePerform: (SEL)aSel in: selObject
{
id (*aSelImp)(id,SEL,id) = (id(*)(id,SEL,id))
objc_msg_lookup(selObject, aSel);
void doIt(elt e)
{
aSelImp(selObject, aSel, e.id_t);
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
[self withElementsInReverseCall:doIt];
return self;
}
- withObjectsInReversePerform: (SEL)aSel in: selObject with: argObject
{
id (*aSelImp)(id,SEL,id,id) = (id(*)(id,SEL,id,id))
objc_msg_lookup(selObject, aSel);
void doIt(elt e)
{
aSelImp(selObject, aSel, e.id_t, argObject);
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
[self withElementsInReverseCall:doIt];
return self;
}
- makeObjectsPerformInReverse: (SEL)aSel
{
void doIt(elt e)
{
[e.id_t perform:aSel];
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
return [self withElementsInReverseCall:doIt];
}
- makeObjectsPerformInReverse: (SEL)aSel with: argObject
{
void doIt(elt e)
{
[e.id_t perform:aSel with:argObject];
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
return [self withElementsInReverseCall:doIt];
}
- withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag
{
unsigned i;
unsigned count = [self count];
for (i = 0; *flag && i < count; i++)
aFunc([self elementAtIndex:i]);
return self;
}
- withKeysAndContentsCall: (void(*)(const elt,elt))aFunc
whileTrue: (BOOL *)flag
{
unsigned index = 0;
void doIt(elt e)
{
aFunc(index, e);
index++;
}
[self withElementsCall:doIt];
return self;
}
// SORTING;
- sortContentsByCalling: (int(*)(elt,elt))aFunc
{
/* Ugly, horrible, inefficient, temporary. */
id collCopy;
void doIt(elt e)
{
[self sortAddElement:e byCalling:aFunc];
}
collCopy = [self shallowCopy];
[self empty];
[collCopy withElementsCall:doIt];
[collCopy free];
return self;
}
- sortAddElement: (elt)newElement byCalling: (int(*)(elt,elt))aFunc
{
unsigned insertionIndex = 0;
BOOL insertionNotFound = YES;
void test(elt e)
{
if (aFunc(newElement, e) < 0)
insertionNotFound = NO;
else
insertionIndex++;
}
[self withElementsCall:test whileTrue:&insertionNotFound];
[self insertElement:newElement atIndex:insertionIndex];
return self;
}
- sortContentsByPerforming: (SEL)aSortingSel
{
int compare(elt e1, elt e2)
{
return (int)[e1.id_t perform:aSortingSel with:e2.id_t];
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
[self sortContentsByCalling:compare];
return self;
}
- sortContentsByPerforming: (SEL)aSortingSel in: selObject
{
int (*aSortingSelImp)(id,SEL,id,id) = (int(*)(id,SEL,id,id))
objc_msg_lookup(selObject, aSortingSel);
int compare(elt e1, elt e2)
{
return aSortingSelImp(selObject, aSortingSel, e1.id_t, e2.id_t);
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
return [self sortContentsByCalling:compare];
}
- sortAddObject: newObject byPerforming: (SEL)aSortingSel
{
int compare(elt e1, elt e2)
{
return (int)[e1.id_t perform:aSortingSel with:e2.id_t];
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
return [self sortAddElement:newObject byCalling:compare];
}
- sortAddObject: newObject byPerforming: (SEL)aSortingSel in: selObject
{
int (*aSortingSelImp)(id,SEL,id,id) = (int(*)(id,SEL,id,id))
objc_msg_lookup(selObject, aSortingSel);
int compare(elt e1, elt e2)
{
return (int)aSortingSelImp(selObject, aSortingSel,
e1.id_t, e2.id_t);
}
if (OBJECTS_REQUIRED_WARNING())
return nil;
return [self sortAddElement:newObject byCalling:compare];
}
// RELATION WITH KeyedCollection;
- insertElement: (elt)newContentElement atKey: (elt)aKey
{
return [self insertElement:newContentElement atIndex:aKey.unsigned_int_t];
}
- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement
{
return [self replaceElementAtIndex:aKey.unsigned_int_t
with:newContentElement];
}
- (elt) removeElementAtKey: (elt)aKey
{
return [self removeElementAtIndex:aKey.unsigned_int_t];
}
- (elt) elementAtKey: (elt)aKey
{
return [self elementAtIndex:aKey.unsigned_int_t];
}
- (BOOL) includesKey: (elt)aKey
{
return [self includesIndex:aKey.unsigned_int_t];
}
- printForDebugger
{
void doIt(elt e)
{
[self printElement:e];
printf(" ");
}
[self withElementsCall:doIt];
printf(" :%s\n", [self name]);
return self;
}
@end
@implementation IndexedCollection (ErrorReporting)
- errorIndex: (unsigned)index beyondRange: (unsigned)over inMethod: (SEL)aSel
{
[self warning:"in %s, index=%u out of range (< %u)",
sel_get_name(aSel), index, over];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.