Artifact a0868f6c97bb1bdab4599c037804ce847974a9057387535f4026cebbe0cc48f6:
- File
src/OFList.m
— part of check-in
[48980f2297]
at
2015-11-29 11:43:05
on branch trunk
— Make properties a requirement and clean up code
This increases the required GCC version from 4.0 to 4.6 (exception:
Apple GCC, which already supports this with >= 4.0 starting with OS X
10.5). Since even GCC 4.6 is really old by now, there is no point in
still supporting something even older and making the code ugly because
of that. While some hardware and OS support was dropped from GCC 4.6
compared to GCC 4.0, there is nothing in there that would be an
interesting target with the exception of BeOS maybe - but a port to BeOS
can also be achieved using the Haiku support. The other dropped OSes are
mostly old versions of OSes while newer ones are still being supported
(and those newer versions of those OSes still support the same
hardware). (user: js, size: 9362) [annotate] [blame] [check-ins using]
/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 * 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 <string.h> #include <assert.h> #import "OFList.h" #import "OFString.h" #import "OFXMLElement.h" #import "OFArray.h" #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" @implementation OFList @synthesize firstListObject = _firstListObject; @synthesize lastListObject = _lastListObject; + (instancetype)list { return [[[self alloc] init] autorelease]; } - initWithSerialization: (OFXMLElement*)element { self = [self init]; @try { void *pool = objc_autoreleasePoolPush(); OFEnumerator *enumerator; OFXMLElement *child; if (![[element name] isEqual: [self className]] || ![[element namespace] isEqual: OF_SERIALIZATION_NS]) @throw [OFInvalidArgumentException exception]; enumerator = [[element elementsForNamespace: OF_SERIALIZATION_NS] objectEnumerator]; while ((child = [enumerator nextObject]) != nil) { void *pool2 = objc_autoreleasePoolPush(); [self appendObject: [child objectByDeserializing]]; objc_autoreleasePoolPop(pool2); } objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; } return self; } - (void)dealloc { of_list_object_t *iter; for (iter = _firstListObject; iter != NULL; iter = iter->next) [iter->object release]; [super dealloc]; } - (of_list_object_t*)appendObject: (id)object { of_list_object_t *listObject; listObject = [self allocMemoryWithSize: sizeof(of_list_object_t)]; listObject->object = [object retain]; listObject->next = NULL; listObject->previous = _lastListObject; if (_lastListObject != NULL) _lastListObject->next = listObject; _lastListObject = listObject; if (_firstListObject == NULL) _firstListObject = listObject; _count++; _mutations++; return listObject; } - (of_list_object_t*)prependObject: (id)object { of_list_object_t *listObject; listObject = [self allocMemoryWithSize: sizeof(of_list_object_t)]; listObject->object = [object retain]; listObject->next = _firstListObject; listObject->previous = NULL; if (_firstListObject != NULL) _firstListObject->previous = listObject; _firstListObject = listObject; if (_lastListObject == NULL) _lastListObject = listObject; _count++; _mutations++; return listObject; } - (of_list_object_t*)insertObject: (id)object beforeListObject: (of_list_object_t*)listObject { of_list_object_t *newListObject; newListObject = [self allocMemoryWithSize: sizeof(of_list_object_t)]; newListObject->object = [object retain]; newListObject->next = listObject; newListObject->previous = listObject->previous; if (listObject->previous != NULL) listObject->previous->next = newListObject; listObject->previous = newListObject; if (listObject == _firstListObject) _firstListObject = newListObject; _count++; _mutations++; return newListObject; } - (of_list_object_t*)insertObject: (id)object afterListObject: (of_list_object_t*)listObject { of_list_object_t *newListObject; newListObject = [self allocMemoryWithSize: sizeof(of_list_object_t)]; newListObject->object = [object retain]; newListObject->next = listObject->next; newListObject->previous = listObject; if (listObject->next != NULL) listObject->next->previous = newListObject; listObject->next = newListObject; if (listObject == _lastListObject) _lastListObject = newListObject; _count++; _mutations++; return newListObject; } - (void)removeListObject: (of_list_object_t*)listObject { if (listObject->previous != NULL) listObject->previous->next = listObject->next; if (listObject->next != NULL) listObject->next->previous = listObject->previous; if (_firstListObject == listObject) _firstListObject = listObject->next; if (_lastListObject == listObject) _lastListObject = listObject->previous; _count--; _mutations++; [listObject->object release]; [self freeMemory: listObject]; } - (id)firstObject { return (_firstListObject != NULL ? _firstListObject->object : nil); } - (id)lastObject { return (_lastListObject != NULL ? _lastListObject->object : nil); } - (size_t)count { return _count; } - (bool)isEqual: (id)object { OFList *list; of_list_object_t *iter, *iter2; if (![object isKindOfClass: [OFList class]]) return false; list = object; if ([list count] != _count) return false; for (iter = _firstListObject, iter2 = [list firstListObject]; iter != NULL && iter2 != NULL; iter = iter->next, iter2 = iter2->next) if (![iter->object isEqual: iter2->object]) return false; /* One is bigger than the other even though we checked the count */ assert(iter == NULL && iter2 == NULL); return true; } - (bool)containsObject: (id)object { of_list_object_t *iter; if (_count == 0) return false; for (iter = _firstListObject; iter != NULL; iter = iter->next) if ([iter->object isEqual: object]) return true; return false; } - (bool)containsObjectIdenticalTo: (id)object { of_list_object_t *iter; if (_count == 0) return false; for (iter = _firstListObject; iter != NULL; iter = iter->next) if (iter->object == object) return true; return false; } - (void)removeAllObjects { of_list_object_t *iter, *next; _mutations++; for (iter = _firstListObject; iter != NULL; iter = next) { next = iter->next; [iter->object release]; [self freeMemory: iter]; } _firstListObject = _lastListObject = NULL; } - copy { OFList *copy = [[[self class] alloc] init]; of_list_object_t *iter, *listObject, *previous; listObject = NULL; previous = NULL; @try { for (iter = _firstListObject; iter != NULL; iter = iter->next) { listObject = [copy allocMemoryWithSize: sizeof(of_list_object_t)]; listObject->object = [iter->object retain]; listObject->next = NULL; listObject->previous = previous; if (copy->_firstListObject == NULL) copy->_firstListObject = listObject; if (previous != NULL) previous->next = listObject; copy->_count++; previous = listObject; } } @catch (id e) { [copy release]; @throw e; } copy->_lastListObject = listObject; return copy; } - (uint32_t)hash { of_list_object_t *iter; uint32_t hash; OF_HASH_INIT(hash); for (iter = _firstListObject; iter != NULL; iter = iter->next) OF_HASH_ADD_HASH(hash, [iter->object hash]); OF_HASH_FINALIZE(hash); return hash; } - (OFString*)description { OFMutableString *ret; of_list_object_t *iter; if (_count == 0) return @"[]"; ret = [OFMutableString stringWithString: @"[\n"]; for (iter = _firstListObject; iter != NULL; iter = iter->next) { void *pool = objc_autoreleasePoolPush(); [ret appendString: [iter->object description]]; if (iter->next != NULL) [ret appendString: @",\n"]; objc_autoreleasePoolPop(pool); } [ret replaceOccurrencesOfString: @"\n" withString: @"\n\t"]; [ret appendString: @"\n]"]; [ret makeImmutable]; return ret; } - (OFXMLElement*)XMLElementBySerializing { OFXMLElement *element; of_list_object_t *iter; element = [OFXMLElement elementWithName: [self className] namespace: OF_SERIALIZATION_NS]; for (iter = _firstListObject; iter != NULL; iter = iter->next) { void *pool = objc_autoreleasePoolPush(); [element addChild: [iter->object XMLElementBySerializing]]; objc_autoreleasePoolPop(pool); } return element; } - (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state objects: (id*)objects count: (int)count { of_list_object_t *listObject; int i; memcpy(&listObject, state->extra, sizeof(listObject)); state->itemsPtr = objects; state->mutationsPtr = &_mutations; if (state->state == 0) { listObject = _firstListObject; state->state = 1; } for (i = 0; i < count; i++) { if (listObject == NULL) return i; objects[i] = listObject->object; listObject = listObject->next; } memcpy(state->extra, &listObject, sizeof(listObject)); return count; } - (OFEnumerator*)objectEnumerator { return [[[OFListEnumerator alloc] initWithList: self mutationsPointer: &_mutations] autorelease]; } @end @implementation OFListEnumerator - initWithList: (OFList*)list mutationsPointer: (unsigned long*)mutationsPtr { self = [super init]; _list = [list retain]; _current = [list firstListObject]; _mutations = *mutationsPtr; _mutationsPtr = mutationsPtr; return self; } - (void)dealloc { [_list release]; [super dealloc]; } - (id)nextObject { id ret; if (*_mutationsPtr != _mutations) @throw [OFEnumerationMutationException exceptionWithObject: _list]; if (_current == NULL) return nil; ret = _current->object; _current = _current->next; return ret; } - (void)reset { if (*_mutationsPtr != _mutations) @throw [OFEnumerationMutationException exceptionWithObject: _list]; _current = [_list firstListObject]; } @end