Artifact 07a8eaaa30a8fffe779565873338766716f92f79ef55f66890dce9b4f24de9e8:
- File
src/OFMutableArray.m
— part of check-in
[13ee56edf3]
at
2014-06-21 21:43:43
on branch trunk
— Move all macros from OFObject.h to macros.h
This means that OFObject.h imports macros.h now, making it unnecessary
to manually import macros.h in almost every file. And while at it, also
import autorelease.h in OFObject.h, so that this doesn't need to be
manually imported in almost every file as well. (user: js, size: 7776) [annotate] [blame] [check-ins using]
/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #include <stdlib.h> #include <string.h> #include <assert.h> #import "OFMutableArray.h" #import "OFMutableArray_adjacent.h" #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" static struct { Class isa; } placeholder; @interface OFMutableArray_placeholder: OFMutableArray @end static void quicksort(OFMutableArray *array, size_t left, size_t right, int options) { of_comparison_result_t ascending, descending; if (options & OF_ARRAY_SORT_DESCENDING) { ascending = OF_ORDERED_DESCENDING; descending = OF_ORDERED_ASCENDING; } else { ascending = OF_ORDERED_ASCENDING; descending = OF_ORDERED_DESCENDING; } while (left < right) { size_t i = left; size_t j = right - 1; id pivot = [array objectAtIndex: right]; do { while ([[array objectAtIndex: i] compare: pivot] != descending && i < right) i++; while ([[array objectAtIndex: j] compare: pivot] != ascending && j > left) j--; if (i < j) [array exchangeObjectAtIndex: i withObjectAtIndex: j]; } while (i < j); if ([[array objectAtIndex: i] compare: pivot] == descending) [array exchangeObjectAtIndex: i withObjectAtIndex: right]; if (i > 0) quicksort(array, left, i - 1, options); left = i + 1; } } @implementation OFMutableArray_placeholder - init { return (id)[[OFMutableArray_adjacent alloc] init]; } - initWithCapacity: (size_t)capacity { return (id)[[OFMutableArray_adjacent alloc] initWithCapacity: capacity]; } - initWithObject: (id)object { return (id)[[OFMutableArray_adjacent alloc] initWithObject: object]; } - initWithObjects: (id)firstObject, ... { id ret; va_list arguments; va_start(arguments, firstObject); ret = [[OFMutableArray_adjacent alloc] initWithObject: firstObject arguments: arguments]; va_end(arguments); return ret; } - initWithObject: (id)firstObject arguments: (va_list)arguments { return (id)[[OFMutableArray_adjacent alloc] initWithObject: firstObject arguments: arguments]; } - initWithArray: (OFArray*)array { return (id)[[OFMutableArray_adjacent alloc] initWithArray: array]; } - initWithObjects: (id const*)objects count: (size_t)count { return (id)[[OFMutableArray_adjacent alloc] initWithObjects: objects count: count]; } - initWithSerialization: (OFXMLElement*)element { return (id)[[OFMutableArray_adjacent alloc] initWithSerialization: element]; } - retain { return self; } - autorelease { return self; } - (void)release { } - (void)dealloc { OF_UNRECOGNIZED_SELECTOR /* Get rid of a stupid warning */ [super dealloc]; } @end @implementation OFMutableArray + (void)initialize { if (self == [OFMutableArray class]) placeholder.isa = [OFMutableArray_placeholder class]; } + alloc { if (self == [OFMutableArray class]) return (id)&placeholder; return [super alloc]; } + (instancetype)arrayWithCapacity: (size_t)capacity { return [[[self alloc] initWithCapacity: capacity] autorelease]; } - init { if (object_getClass(self) == [OFMutableArray class]) { @try { [self doesNotRecognizeSelector: _cmd]; abort(); } @catch (id e) { [self release]; @throw e; } } return [super init]; } - initWithCapacity: (size_t)capacity { OF_INVALID_INIT_METHOD } - copy { return [[OFArray alloc] initWithArray: self]; } - (void)addObject: (id)object { [self insertObject: object atIndex: [self count]]; } - (void)addObjectsFromArray: (OFArray*)array { [self insertObjectsFromArray: array atIndex: [self count]]; } - (void)insertObject: (id)object atIndex: (size_t)index { OF_UNRECOGNIZED_SELECTOR } - (void)insertObjectsFromArray: (OFArray*)array atIndex: (size_t)index { void *pool = objc_autoreleasePoolPush(); OFEnumerator *enumerator = [array objectEnumerator]; size_t i, count = [array count]; for (i = 0; i < count; i++) { id object = [enumerator nextObject]; assert(object != nil); [self insertObject: object atIndex: index + i]; } objc_autoreleasePoolPop(pool); } - (void)replaceObjectAtIndex: (size_t)index withObject: (id)object { OF_UNRECOGNIZED_SELECTOR } - (void)setObject: (id)object atIndexedSubscript: (size_t)index { [self replaceObjectAtIndex: index withObject: object]; } - (void)replaceObject: (id)oldObject withObject: (id)newObject { size_t i, count; if (oldObject == nil || newObject == nil) @throw [OFInvalidArgumentException exception]; count = [self count]; for (i = 0; i < count; i++) { if ([[self objectAtIndex: i] isEqual: oldObject]) { [self replaceObjectAtIndex: i withObject: newObject]; return; } } } - (void)replaceObjectIdenticalTo: (id)oldObject withObject: (id)newObject { size_t i, count; if (oldObject == nil || newObject == nil) @throw [OFInvalidArgumentException exception]; count = [self count]; for (i = 0; i < count; i++) { if ([self objectAtIndex: i] == oldObject) { [self replaceObjectAtIndex: i withObject: newObject]; return; } } } - (void)removeObjectAtIndex: (size_t)index { OF_UNRECOGNIZED_SELECTOR } - (void)removeObject: (id)object { size_t i, count; if (object == nil) @throw [OFInvalidArgumentException exception]; count = [self count]; for (i = 0; i < count; i++) { if ([[self objectAtIndex: i] isEqual: object]) { [self removeObjectAtIndex: i]; return; } } } - (void)removeObjectIdenticalTo: (id)object { size_t i, count; if (object == nil) @throw [OFInvalidArgumentException exception]; count = [self count]; for (i = 0; i < count; i++) { if ([self objectAtIndex: i] == object) { [self removeObjectAtIndex: i]; return; } } } - (void)removeObjectsInRange: (of_range_t)range { size_t i; for (i = 0; i < range.length; i++) [self removeObjectAtIndex: range.location]; } - (void)removeLastObject { size_t count = [self count]; if (count == 0) return; [self removeObjectAtIndex: count - 1]; } - (void)removeAllObjects { [self removeObjectsInRange: of_range(0, [self count])]; } #ifdef OF_HAVE_BLOCKS - (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block { [self enumerateObjectsUsingBlock: ^ (id object, size_t index, bool *stop) { id new = block(object, index); if (new != object) [self replaceObjectAtIndex: index withObject: new]; }]; } #endif - (void)exchangeObjectAtIndex: (size_t)index1 withObjectAtIndex: (size_t)index2 { id object1 = [self objectAtIndex: index1]; id object2 = [self objectAtIndex: index2]; [object1 retain]; @try { [self replaceObjectAtIndex: index1 withObject: object2]; [self replaceObjectAtIndex: index2 withObject: object1]; } @finally { [object1 release]; } } - (void)sort { [self sortWithOptions: 0]; } - (void)sortWithOptions: (int)options { size_t count = [self count]; if (count == 0 || count == 1) return; quicksort(self, 0, count - 1, options); } - (void)reverse { size_t i, j, count = [self count]; if (count == 0 || count == 1) return; for (i = 0, j = count - 1; i < j; i++, j--) [self exchangeObjectAtIndex: i withObjectAtIndex: j]; } - (void)makeImmutable { } @end