This is Collection.m in view mode; [Download] [Up]
/* Implementation for Objective-C Collection 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/Collection.h> #include <coll/CollectionPrivate.h> #include <objc/objc-api.h> #include <stdio.h> /* for vfprintf() in "-warning:" */ #include <stdarg.h> const elt COLL_NO_ELEMENT = ((elt)(~0L)); /* I'd like this to be made public */ int objc_sizeof_type(const char* type) { switch(*type) { case _C_ID: return sizeof(id); break; case _C_CLASS: return sizeof(Class*); break; case _C_SEL: return sizeof(SEL); break; case _C_CHR: return sizeof(char); break; case _C_UCHR: return sizeof(unsigned char); break; case _C_SHT: return sizeof(short); break; case _C_USHT: return sizeof(unsigned short); break; case _C_INT: case _C_LNG: return sizeof(int); break; case _C_UINT: case _C_ULNG: return sizeof(unsigned int); break; case _C_ATOM: case _C_CHARPTR: return sizeof(char*); break; default: fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type); abort(); } } @implementation Collection + initialize { if (self == [Collection class]) { /* This should be checked at compile time. Why do I get a parse error when I use sizeof() in a #if () statement? */ if (sizeof(elt) != sizeof(void*)) [self error:"(sizeof(elt) == sizeof(void*)) not satisfied"]; [self setVersion:-1]; /* alpha release */ } return self; } // INITIALIZING AND FREEING; /* This is the designated initializer of this class */ - initDescription:(const char *)type { [super init]; if (objc_sizeof_type(type) > sizeof(elt)) [self error: "Collection can't store elements with size greater than (elt)"]; OBJC_MALLOC(_description, char, strlen(type)+1); strcpy(_description, type); /* This is not portable... Change this switch. */ switch (*_description) { case _C_CHARPTR: case _C_ATOM: _compare_func = (compare_func_type)coll_compare_strings; break; case _C_ID: case _C_CLASS: /* isEqual: on classes works well? */ _compare_func = (compare_func_type)coll_compare_objects; break; case _C_PTR: case _C_SEL: _compare_func = (compare_func_type)coll_compare_ptrs; break; case _C_INT: case _C_UINT: case _C_FLT: /* Yipes */ _compare_func = (compare_func_type)coll_compare_ints; break; case _C_LNG: case _C_ULNG: _compare_func = (compare_func_type)coll_compare_long_ints; break; default : [self error:"Element type (%s) not supported.\n", _description]; } return self; } - initDescription:(const char *)type with: (unsigned)numElements, ... { va_list ap; [self initDescription:type]; va_start(ap, numElements); // We should use objc_msg_lookup here?; while (numElements--) [self addElement:va_arg(ap, elt)]; va_end(ap); return self; } - init { return [self initDescription:"@"]; } - initWith: (unsigned)numElements, ... { va_list ap; [self init]; va_start(ap, numElements); // We should use objc_msg_lookup here?; while (numElements--) [self addElement:va_arg(ap, elt)]; va_end(ap); return self; } - free { OBJC_FREE(_description); return [super free]; } - freeContents { if (CONTAINS_OBJECTS) [self makeObjectsPerform:@selector(free)]; [self empty]; return self; } // ADDING; - addElement: (elt)newElement { return [self subclassResponsibility:_cmd]; } - addElementIfAbsent: (elt)newElement { if (![self includesElement:newElement]) return [self addElement:newElement]; return nil; } - addContentsOf: (id <Collecting>)aCollection { id (*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) objc_msg_lookup(self, @selector(addElement:)); /* Should all these doIt()'s be 'static inline' ? */ void doIt(elt e) { addElementImp(self, @selector(addElement:), e); } [aCollection withElementsCall:doIt]; return self; } - addContentsOfIfAbsent: (id <Collecting>)aCollection { id (*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) objc_msg_lookup(self, @selector(addElement:)); BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) objc_msg_lookup(self, @selector(includesElement:)); void doIt(elt e) { if (!includesElementImp(self, @selector(includesElement), e)) addElementImp(self, @selector(addElement:), e); } [aCollection withElementsCall:doIt]; return self; } - addCount: (unsigned)count, ... { va_list ap; va_start(ap, count); while (count--) [self addElement:va_arg(ap, elt)]; va_end(ap); return self; } // REMOVING AND REPLACING; - (elt) removeElement: (elt)oldElement { return [self subclassResponsibility:_cmd]; } - (elt ) removeAllOccurrencesOfElement: (elt )oldElement { elt r; BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) objc_msg_lookup(self, @selector(includesElement:)); elt (*removeElementImp)(id,SEL,elt) = (elt(*)(id,SEL,elt)) objc_msg_lookup(self, @selector(removeElement:)); while (includesElementImp(self, @selector(includesElement:), oldElement)) { r = removeElementImp(self, @selector(removeElement:), oldElement); } return r; } - removeContentsIn: (id <Collecting>)aCollection { BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) objc_msg_lookup(self, @selector(includesElement:)); elt (*removeElementImp)(id,SEL,elt) = (elt(*)(id,SEL,elt)) objc_msg_lookup(self, @selector(removeElement:)); void doIt(elt e) { if (includesElementImp(self, @selector(includesElement:), e)) removeElementImp(self, @selector(removeElement:), e); } [aCollection withElementsCall:doIt]; return self; } - removeContentsNotIn: (id <Collecting>)aCollection { BOOL (*includesElementImp)(id,SEL,elt) = (BOOL(*)(id,SEL,elt)) objc_msg_lookup(aCollection, @selector(includesElement:)); elt (*removeElementImp)(id,SEL,elt) = (elt(*)(id,SEL,elt)) objc_msg_lookup(self, @selector(removeElement:)); void doIt(elt e) { if (!includesElementImp(aCollection, @selector(includesElement:), e)) removeElementImp(self, @selector(removeElement:), e); } [self withElementsCall:doIt]; return self; } /* remember this has to be overridden for IndexedCollection's */ - (elt) replaceElement: (elt )oldElement with: (elt )newElement { elt ret; ret = [self removeElement:oldElement]; [self addElement:newElement]; return ret; } - (elt) replaceAllOccurrencesOfElement: (elt)oldElement with: (elt)newElement { elt ret; // Use objc_msg_lookup here also; if (_compare_func(oldElement.void_ptr_t, newElement.void_ptr_t)) return self; while ([self includesElement:oldElement]) ret = [self replaceElement:oldElement with:newElement]; return ret; } - uniqueContents { // Use objc_msg_lookup here also; void doIt(elt e) { while ([self occurrencesOfElement:e] > 1) [self removeElement:e]; } [self withElementsCall:doIt]; return self; } - empty { // Use objc_msg_lookup here also; void doIt(elt e) { [self removeElement:e]; } [[[self shallowCopy] withElementsCall:doIt] free]; return self; } // TESTING; - (BOOL) isEmpty { return ([self count] == 0); } /* Potentially inefficient, may be overridden in subclasses */ - (BOOL) includesElement: (elt)anElement { BOOL test(elt e) { if (_compare_func(anElement.void_ptr_t, e.void_ptr_t)) return YES; else return NO; } return [self trueForAnyByCalling:test]; } - (BOOL) includesSubsetOf: (id <Collecting>)aCollection { BOOL test(elt e) { return [self includesElement:e]; } return [aCollection trueForAllByCalling:test]; } - (BOOL) includesSameContents: (id <Collecting>)aCollection { // not very efficient; return ([self includesSubsetOf:aCollection] && [aCollection includesSubsetOf:self]); } /* Is this what we want? */ - (BOOL) isEqual: anObject { if ([self class] == [anObject class] && [self includesSameContents: anObject]) return YES; else return NO; } - (BOOL) isDisjointFrom: (id <Collecting>)aCollection { // Use objc_msg_lookup here also; BOOL flag = YES; void doIt(elt e) { if (![aCollection includesElement:e]) flag = NO; } [self withElementsCall:doIt whileTrue:&flag]; return !flag; } - (BOOL) trueForAllByCalling: (BOOL(*)(elt))aFunc { BOOL flag = YES; void doIt(elt e) { if (!(aFunc(e))) flag = NO; } [self withElementsCall:doIt whileTrue:&flag]; return flag; } - (BOOL) trueForAnyByCalling: (BOOL(*)(elt))aFunc; { BOOL flag = YES; void doIt(elt e) { if (aFunc(e)) flag = NO; } [self withElementsCall:doIt whileTrue:&flag]; return !flag; } /* Inefficient, so should be overridden in subclasses. */ - (unsigned) count { unsigned n = 0; void doIt(elt e) { n++; } [self withElementsCall:doIt]; return n; } - (unsigned) occurrencesOfElement: (elt)anElement { unsigned count = 0; void doIt(elt e) { if (_compare_func(anElement.void_ptr_t, e.void_ptr_t)) count++; } [self withElementsCall:doIt]; return count; } - (unsigned) occurrencesOfObject: anObject { return [self occurrencesOfElement:anObject]; } - (const char *) contentsDescription { return _description; } - (BOOL) containsObjects { return CONTAINS_OBJECTS; } // ENUMERATING; - (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState { [self subclassResponsibility:_cmd]; return NO; } /* Getting objects one at a time. Pass NULL enumState to start. It will return COLL_NO_ELEMENT when done. */ - nextObject: (void**)enumState { elt o; if ([self getNextElement:&o withEnumState:enumState]) return o.id_t; else return COLL_NO_OBJECT; } - withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag { void *enumState = 0; elt e; while (*flag && [self getNextElement:&e withEnumState:&enumState]) aFunc(e); return self; } - withElementsCall: (void(*)(elt))aFunc { BOOL flag = YES; return [self withElementsCall:aFunc whileTrue:&flag]; } // COPYING; - shallowCopy { return [self shallowCopyAs:[self species]]; } /* the copy to be filled by -shallowCopySelect, -shallowCopyCollect, etc... */ - emptyCopyAs: aCollectionClass { return [[aCollectionClass alloc] initDescription:_description]; } /* the right thing for ordered objects also? */ - shallowCopyAs: (id <Collecting>)aCollectionClass { id newColl = [self emptyCopyAs:aCollectionClass]; id (*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) objc_msg_lookup(newColl, @selector(addElement:)); void doIt(elt e) { addElementImp(newColl, @selector(addElement:), e); } [self withElementsCall:doIt]; return newColl; } - deepen { /* could use objc_msg_lookup here too */ void doIt(elt o) { [self replaceElement:o with:[[o.id_t shallowCopy] deepen]]; } if (OBJECTS_REQUIRED_WARNING()) return self; /* Is this shallowCopy necessary? I think so, unfortunately. */ [[[self shallowCopy] withElementsCall:doIt] free]; return self; } - species { return [self class]; } // COPYING ENUMERATORS; - shallowCopySelectByCalling: (BOOL(*)(elt))aFunc { id newColl = [self emptyCopyAs:[self species]]; id (*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) objc_msg_lookup(newColl, @selector(addElement:)); void doIt(elt e) { if (aFunc(e)) addElementImp(newColl, @selector(addElement:), e); } [self withElementsCall:doIt]; return newColl; } - shallowCopyRejectByCalling: (BOOL(*)(elt))aFunc { id newColl = [self emptyCopyAs:[self species]]; id (*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) objc_msg_lookup(newColl, @selector(addElement:)); void doIt(elt e) { if (!aFunc(e)) addElementImp(newColl, @selector(addElement:), e); } return newColl; } - shallowCopyCollectByCalling: (elt (*)(elt))aFunc { id newColl = [self emptyCopyAs:[self species]]; id (*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt)) objc_msg_lookup(newColl, @selector(addElement:)); void doIt(elt e) { addElementImp(newColl, @selector(addElement:), aFunc(e)); } return newColl; } // NON-COPYING ENUMERATORS; - (elt ) detectElementByCalling: (BOOL(*)(elt))aFunc { BOOL flag = YES; elt detectedElement; void doIt(elt e) { if (aFunc(e)) { flag = NO; detectedElement = e; } } detectedElement = COLL_NO_ELEMENT; [self withElementsCall:doIt whileTrue:&flag]; return detectedElement; } - (elt) maxElementByCalling: (int(*)(elt,elt))aFunc { elt max; BOOL firstTime = YES; void doIt(elt e) { if (firstTime) { firstTime = NO; max = e; } else { if (aFunc(e,max) > 0) max = e; } } [self withElementsCall:doIt]; return max; } - (elt) minElementByCalling: (int(*)(elt,elt))aFunc { elt min; BOOL firstTime = YES; void doIt(elt e) { if (firstTime) { firstTime = NO; min = e; } else { if (aFunc(e,min) < 0) min = e; } } [self withElementsCall:doIt]; return min; } - inject: (void*)initialData byCalling: (void* (*)(void*,elt))aFunc { void doIt(elt e) { initialData = aFunc(initialData, e); } [self withElementsCall:doIt]; return self; } // SMALLTALK BLOCKS AS SELECTORS; - (BOOL) trueForAllByPerforming: (SEL)aBoolSel in: selObject { BOOL (*aBoolSelImp)(id,SEL,id) = (BOOL(*)(id,SEL,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(elt e) { return aBoolSelImp(selObject, aBoolSel, e.id_t); } if (OBJECTS_REQUIRED_WARNING()) return NO; return [self trueForAllByCalling:test]; } - (BOOL) trueForAllByPerforming: (SEL)aBoolSel in: selObject with: argObject { BOOL (*aBoolSelImp)(id,SEL,id,id) = (BOOL(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(elt e) { return aBoolSelImp(selObject, aBoolSel, e.id_t, argObject); } if (OBJECTS_REQUIRED_WARNING()) return NO; return [self trueForAllByCalling:test]; } - (BOOL) trueForAllByPerforming: (SEL)aBoolSel { BOOL test(elt e) { /* Is this the correct casting magic? */ return (unsigned)[e.id_t perform:aBoolSel]; } if (OBJECTS_REQUIRED_WARNING()) return NO; return [self trueForAllByCalling:test]; } - (BOOL) trueForAllByPerforming: (SEL)aBoolSel with: argObject { BOOL test(elt e) { return (unsigned)[e.id_t perform:aBoolSel with:argObject]; } if (OBJECTS_REQUIRED_WARNING()) return NO; return [self trueForAllByCalling:test]; } - (BOOL) trueForAnyByPerforming: (SEL)aBoolSel in: selObject { BOOL (*aBoolSelImp)(id,SEL,id) = (BOOL(*)(id,SEL,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(elt e) { return aBoolSelImp(selObject, aBoolSel, e.id_t); } if (OBJECTS_REQUIRED_WARNING()) return NO; return [self trueForAnyByCalling:test]; } - (BOOL) trueForAnyByPerforming: (SEL)aBoolSel in: selObject with: argObject { BOOL (*aBoolSelImp)(id,SEL,id,id) = (BOOL(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(elt e) { return aBoolSelImp(selObject, aBoolSel, e.id_t, argObject); } if (OBJECTS_REQUIRED_WARNING()) return NO; return [self trueForAnyByCalling:test]; } - (BOOL) trueForAnyByPerforming: (SEL)aBoolSel { BOOL test(elt e) { return (unsigned)[e.id_t perform:aBoolSel]; } if (OBJECTS_REQUIRED_WARNING()) return NO; return [self trueForAnyByCalling:test]; } - (BOOL) trueForAnyByPerforming: (SEL)aBoolSel with: argObject { BOOL test(elt e) { return (unsigned)[e.id_t perform:aBoolSel with:argObject]; } if (OBJECTS_REQUIRED_WARNING()) return NO; return [self trueForAnyByCalling:test]; } - makeObjectsPerform: (SEL)aSel { void doIt(elt e) { [e.id_t perform:aSel]; } if (OBJECTS_REQUIRED_WARNING()) return nil; [self withElementsCall:doIt]; return self; } - makeObjectsPerform: (SEL)aSel with: argObject { void doIt(elt e) { [e.id_t perform:aSel with:argObject]; } if (OBJECTS_REQUIRED_WARNING()) return nil; [self withElementsCall:doIt]; return self; } - shallowCopySelectByPerforming: (SEL)aBoolSel in: selObject { BOOL (*aBoolSelImp)(id,SEL,id) = (BOOL(*)(id,SEL,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(elt e) { return aBoolSelImp(selObject, aBoolSel, e.id_t); } return [self shallowCopySelectByCalling:test]; } - shallowCopySelectByPerforming: (SEL)aBoolSel in: selObject with: argObject { BOOL (*aBoolSelImp)(id,SEL,id,id) = (BOOL(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(elt e) { return aBoolSelImp(selObject, aBoolSel, e.id_t, argObject); } return [self shallowCopySelectByCalling:test]; } - shallowCopySelectByPerforming: (SEL)aBoolSel { BOOL test(elt e) { return (unsigned)[e.id_t perform:aBoolSel]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self shallowCopySelectByCalling:test]; } - shallowCopySelectByPerforming: (SEL)aBoolSel with: argObject { BOOL test(elt e) { return (unsigned)[e.id_t perform:aBoolSel with:argObject]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self shallowCopySelectByCalling:test]; } - shallowCopyRejectByPerforming: (SEL)aBoolSel in: selObject { BOOL (*aBoolSelImp)(id,SEL,id) = (BOOL(*)(id,SEL,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(elt e) { return aBoolSelImp(selObject, aBoolSel, e.id_t); } return [self shallowCopyRejectByCalling:test]; } - shallowCopyRejectByPerforming: (SEL)aBoolSel in: selObject with: argObject { BOOL (*aBoolSelImp)(id,SEL,id,id) = (BOOL(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(elt e) { return aBoolSelImp(selObject, aBoolSel, e.id_t, argObject); } return [self shallowCopyRejectByCalling:test]; } - shallowCopyRejectByPerforming: (SEL)aBoolSel { BOOL test(elt e) { return (unsigned)[e.id_t perform:aBoolSel]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self shallowCopyRejectByCalling:test]; } - shallowCopyRejectByPerforming: (SEL)aBoolSel with: argObject { BOOL test(elt e) { return (unsigned)[e.id_t perform:aBoolSel with:argObject]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self shallowCopyRejectByCalling:test]; } - shallowCopyCollectByPerforming: (SEL)aSel in: selObject { id (*aSelImp)(id,SEL,id) = (id(*)(id,SEL,id)) objc_msg_lookup(selObject, aSel); elt returnIt(elt e) { return (elt)aSelImp(selObject, aSel, e.id_t); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self shallowCopyCollectByCalling:returnIt]; } - shallowCopyCollectByPerforming: (SEL)aSel in: selObject with: argObject { id (*aSelImp)(id,SEL,id,id) = (id(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aSel); elt returnIt(elt e) { return (elt)aSelImp(selObject, aSel, e.id_t, argObject); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self shallowCopyCollectByCalling:returnIt]; } - shallowCopyCollectByPerforming: (SEL)aSel { elt returnIt(elt e) { return (elt)[e.id_t perform:aSel]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self shallowCopyCollectByCalling:returnIt]; } - shallowCopyCollectByPerforming: (SEL)aSel with: argObject { elt returnIt(elt e) { return (elt)[e.id_t perform:aSel with:argObject]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self shallowCopyCollectByCalling:returnIt]; } - detectByPerforming: (SEL)aBoolSel in: selObject { BOOL (*aBoolSelImp)(id,SEL,id) = (BOOL(*)(id,SEL,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(id e) { return aBoolSelImp(selObject, aBoolSel, e); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self detectObjectByCalling:test]; } - detectByPerforming: (SEL)aBoolSel in: selObject with: argObject { BOOL (*aBoolSelImp)(id,SEL,id,id) = (BOOL(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aBoolSel); BOOL test(id e) { return aBoolSelImp(selObject, aBoolSel, e, argObject); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self detectObjectByCalling:test]; } - detectByPerforming: (SEL)aBoolSel { BOOL test(id e) { return (unsigned)[e perform:aBoolSel]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self detectObjectByCalling:test]; } - detectByPerforming: (SEL)aBoolSel with: argObject { BOOL test(id e) { return (unsigned)[e perform:aBoolSel with:argObject]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self detectObjectByCalling:test]; } - maxObjectByCalling: (int(*)(id,id))aFunc { id max; BOOL firstTime = YES; void doIt(id e) { if (firstTime) { firstTime = NO; max = e; } else { if (aFunc(e,max) > 0) max = e; } } if (OBJECTS_REQUIRED_WARNING()) return nil; [self withObjectsCall:doIt]; return max; } - minObjectByCalling: (int(*)(id,id))aFunc { id min; BOOL firstTime = YES; void doIt(id e) { if (firstTime) { firstTime = NO; min = e; } else { if (aFunc(e,min) < 0) min = e; } } if (OBJECTS_REQUIRED_WARNING()) return nil; [self withObjectsCall:doIt]; return min; } - maxByPerforming: (SEL)aSortingSel { int compare(id e1, id e2) { return (int)[e1 perform:aSortingSel with:e2]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self maxObjectByCalling:compare]; } - maxByPerforming: (SEL)aSortingSel in: selObject { int (*aSortingSelImp)(id,SEL,id,id) = (int(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aSortingSel); int compare(id e1, id e2) { return aSortingSelImp(selObject, aSortingSel, e1, e2); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self maxObjectByCalling:compare]; } - minByPerforming: (SEL)aSortingSel { int compare(id e1, id e2) { return (int)[e1 perform:aSortingSel with:e2]; } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self minObjectByCalling:compare]; } - minByPerforming: (SEL)aSortingSel in: selObject { int (*aSortingSelImp)(id,SEL,id,id) = (int(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aSortingSel); int compare(id e1, id e2) { return aSortingSelImp(selObject, aSortingSel, e1, e2); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self minObjectByCalling:compare]; } - inject: initialArgObject byPerforming: (SEL)aSel in: selObject { id (*aSelImp)(id,SEL,id,id) = (id(*)(id,SEL,id,id)) objc_msg_lookup(selObject, aSel); void* returnIt(void* d, elt e) { return aSelImp(selObject, aSel, (id)d, e.id_t); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self inject:initialArgObject byCalling:returnIt]; } // OBJECT-COMPATIBLE MESSAGE NAMES // ADDING; - addObject: newObject { return [self addElement:newObject]; } - addObjectIfAbsent: newObject { return [self addElementIfAbsent:newObject]; } // REMOVING AND REPLACING; - removeObject: oldObject { return [self removeElement:oldObject].id_t; } - removeAllOccurrencesOfObject: oldObject { return (id)[self removeAllOccurrencesOfObject:oldObject]; } - replaceObject: oldObject with: newObject { return [self replaceElement:oldObject with:newObject].id_t; } - replaceAllOccurrencesOfObject: oldObject with: newObject { return [self replaceAllOccurrencesOfElement:oldObject with:newObject].id_t; } // TESTING; - (BOOL) includesObject: anObject { return [self includesElement:anObject]; } // ENUMERATING - withObjectsCall: (void(*)(id))aFunc { void doIt(elt e) { aFunc(e.id_t); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self withElementsCall:doIt]; } - withObjectsCall: (void(*)(id))aFunc whileTrue:(BOOL *)flag { void doIt(elt e) { aFunc(e.id_t); } if (OBJECTS_REQUIRED_WARNING()) return nil; return [self withElementsCall:doIt whileTrue:flag]; } - withObjectsPerform: (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 withElementsCall:doIt]; return self; } - withObjectsPerform: (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 withElementsCall:doIt]; return self; } // NON-COPYING ENUMERATORS; - detectObjectByCalling: (BOOL(*)(id))aFunc { if (OBJECTS_REQUIRED_WARNING()) return nil; return [self detectElementByCalling:(BOOL(*)(elt))aFunc].id_t; } /* This printing stuff will change when we get Stream objects */ + printElement: (elt)anElement description: (const char *)type { switch (*type) { case _C_CHARPTR: case _C_ATOM: printf("\"%s\"", anElement.char_ptr_t); break; case _C_ID: case _C_CLASS: printf("%s:0x%x", [anElement.id_t name], anElement.unsigned_int_t); break; case _C_PTR: printf("0x%x", anElement.unsigned_int_t); break; case _C_SEL: printf("%s", sel_get_name(anElement.SEL_t)); break; case _C_INT: printf("%d", anElement.int_t); break; case _C_UINT: case _C_LNG: case _C_ULNG: printf("%d", anElement.unsigned_int_t); break; case _C_FLT: printf("%f", anElement.float_t); break; default : printf("unknown?"); } return self; } - printElement: (elt)anElement { [[self class] printElement:anElement description:_description]; return self; } - printForDebugger { void doIt(elt e) { [self printElement:e]; printf(" "); } [self withElementsCall:doIt]; printf(" :%s\n", [self name]); return self; } - oldprintForDebugger { void *s = 0; elt e; while ([self getNextElement:&e withEnumState:&s]) [self printElement:e]; printf(" :%s\n", [self name]); return self; } // WARNING; /* We should have a more general warning mechanism. */ static classWarn = YES; /* print warnings or not */ - warning:(const char *)aString,... { #define FMT "warning: %s (%s)\n %s\n" char fmt[(strlen(FMT)+strlen(object_get_class_name(self)) +((aString!=0)?strlen(aString):0)+8)]; va_list ap; if (classWarn) { sprintf(fmt, FMT, object_get_class_name(self), object_is_instance(self)?"instance":"class", (aString!=0)?aString:""); va_start(ap, aString); vfprintf(stderr, fmt, ap); va_end(ap); } return self; #undef FMT } @end @implementation Collection (ErrorReporting) // ERROR REPORTING; - errorElementNotFound: (elt)anElement inMethod: (SEL)aSel { [self warning:"in %s, couldn't find element 0x%x", sel_get_name(aSel), anElement.unsigned_int_t]; return self; } - errorObjectsRequiredInMethod: (SEL)aSel { [self warning:"in %s, requires contents to be objects", sel_get_name(aSel)]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.