Artifact 7a63d8437bd922083b213945788af05484e11767096f4014f67cec414939d3a7:
- File
src/OFCountedMapTableSet.m
— part of check-in
[6ce0093f8d]
at
2023-04-10 19:22:32
on branch trunk
— Remove OFSerialization
While the idea sounds nice that the tag name is the class, this means the
serialization includes whether something is mutable or immutable. This means
doing as much as making something immutable changes the serialization, which
can then cause issues after being deserialized. (user: js, size: 3576) [annotate] [blame] [check-ins using] [more...]
/* * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im> * * 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" #import "OFCountedMapTableSet.h" #import "OFArray.h" #import "OFMapTable.h" #import "OFMutableMapTableSet.h" #import "OFString.h" #import "OFXMLAttribute.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFEnumerationMutationException.h" #import "OFOutOfRangeException.h" @implementation OFCountedMapTableSet + (void)initialize { if (self == [OFCountedMapTableSet class]) [self inheritMethodsFromClass: [OFMutableMapTableSet class]]; } - (instancetype)initWithSet: (OFSet *)set { self = [self init]; @try { void *pool = objc_autoreleasePoolPush(); if ([set isKindOfClass: [OFCountedSet class]]) { OFCountedSet *countedSet = (OFCountedSet *)set; for (id object in countedSet) { size_t count = [countedSet countForObject: object]; for (size_t i = 0; i < count; i++) [self addObject: object]; } } else for (id object in set) [self addObject: object]; objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; } return self; } - (instancetype)initWithArray: (OFArray *)array { self = [self init]; @try { id const *objects = array.objects; size_t count = array.count; for (size_t i = 0; i < count; i++) [self addObject: objects[i]]; } @catch (id e) { [self release]; @throw e; } return self; } - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { self = [self init]; @try { for (size_t i = 0; i < count; i++) [self addObject: objects[i]]; } @catch (id e) { [self release]; @throw e; } return self; } - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { self = [self init]; @try { id object; [self addObject: firstObject]; while ((object = va_arg(arguments, id)) != nil) [self addObject: object]; } @catch (id e) { [self release]; @throw e; } return self; } - (size_t)countForObject: (id)object { return (size_t)(uintptr_t)[_mapTable objectForKey: object]; } #ifdef OF_HAVE_BLOCKS - (void)enumerateObjectsAndCountUsingBlock: (OFCountedSetEnumerationBlock)block { @try { [_mapTable enumerateKeysAndObjectsUsingBlock: ^ (void *key, void *object, bool *stop) { block(key, (size_t)(uintptr_t)object, stop); }]; } @catch (OFEnumerationMutationException *e) { @throw [OFEnumerationMutationException exceptionWithObject: self]; } } #endif - (void)addObject: (id)object { size_t count = (size_t)(uintptr_t)[_mapTable objectForKey: object]; if (SIZE_MAX - count < 1 || UINTPTR_MAX - count < 1) @throw [OFOutOfRangeException exception]; [_mapTable setObject: (void *)(uintptr_t)(count + 1) forKey: object]; } - (void)removeObject: (id)object { size_t count = (size_t)(uintptr_t)[_mapTable objectForKey: object]; if (count == 0) return; count--; if (count > 0) [_mapTable setObject: (void *)(uintptr_t)count forKey: object]; else [_mapTable removeObjectForKey: object]; } - (void)removeAllObjects { [_mapTable removeAllObjects]; } - (void)makeImmutable { } @end