Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -185,19 +185,19 @@ - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { size_t count = 1; va_list argumentsCopy; id *objects; + + if (firstObject == nil) + return [self init]; va_copy(argumentsCopy, arguments); while (va_arg(argumentsCopy, id) != nil) count++; @try { - if (firstObject == nil) - @throw [OFInvalidArgumentException exception]; - objects = OFAllocMemory(count, sizeof(id)); } @catch (id e) { [self release]; @throw e; } Index: src/OFCountedSet.m ================================================================== --- src/OFCountedSet.m +++ src/OFCountedSet.m @@ -28,10 +28,16 @@ @interface OFPlaceholderCountedSet: OFCountedSet @end @implementation OFPlaceholderCountedSet +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { return (id)[[OFConcreteCountedSet alloc] init]; } @@ -67,10 +73,13 @@ - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { return (id)[[OFConcreteCountedSet alloc] initWithObject: firstObject arguments: arguments]; } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif OF_SINGLETON_METHODS @end @implementation OFCountedSet Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -256,17 +256,15 @@ } @catch (id e) { [self release]; @throw e; } - @try { - return [self initWithObjects: objects - forKeys: keys - count: count]; - } @finally { - objc_autoreleasePoolPop(pool); - } + self = [self initWithObjects: objects forKeys: keys count: count]; + + objc_autoreleasePoolPop(pool); + + return self; } #ifdef __clang__ /* We intentionally don't call into super, so silence the warning. */ # pragma clang diagnostic push @@ -298,20 +296,23 @@ - (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments { size_t count = 1; id *objects = NULL, *keys = NULL; va_list argumentsCopy; + + if (firstKey == nil) + return [self init]; va_copy(argumentsCopy, arguments); while (va_arg(argumentsCopy, id) != nil) count++; @try { size_t i = 0; id key, object; - if (firstKey == nil || count % 2 != 0) + if (count % 2 != 0) @throw [OFInvalidArgumentException exception]; count /= 2; objects = OFAllocMemory(count, sizeof(id)); Index: src/OFMutableSet.h ================================================================== --- src/OFMutableSet.h +++ src/OFMutableSet.h @@ -36,18 +36,25 @@ * @param capacity The initial capacity for the OFMutableSet * @return A new autoreleased OFMutableSet */ + (instancetype)setWithCapacity: (size_t)capacity; +/** + * @brief Initializes an already allocated OFMutableSet to be empty. + * + * @return An initialized OFMutableSet + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an already allocated OFMutableSet with enough memory to * hold the specified number of objects. * * @param capacity The initial capacity for the OFMutableSet * @return An initialized OFMutableSet */ -- (instancetype)initWithCapacity: (size_t)capacity; +- (instancetype)initWithCapacity: (size_t)capacity OF_DESIGNATED_INITIALIZER; /** * @brief Adds the specified object to the set. * * @param object The object to add to the set Index: src/OFMutableSet.m ================================================================== --- src/OFMutableSet.m +++ src/OFMutableSet.m @@ -27,10 +27,16 @@ @interface OFPlaceholderMutableSet: OFMutableSet @end @implementation OFPlaceholderMutableSet +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { return (id)[[OFConcreteMutableSet alloc] init]; } @@ -71,10 +77,13 @@ - (instancetype)initWithCapacity: (size_t)capacity { return (id)[[OFConcreteMutableSet alloc] initWithCapacity: capacity]; } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif OF_SINGLETON_METHODS @end @implementation OFMutableSet @@ -95,15 +104,34 @@ + (instancetype)setWithCapacity: (size_t)capacity { return [[[self alloc] initWithCapacity: capacity] autorelease]; } + +- (instancetype)init +{ + return [super init]; +} + +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + OF_INVALID_INIT_METHOD +} - (instancetype)initWithCapacity: (size_t)capacity { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (id)copy { return [[OFSet alloc] initWithSet: self]; } Index: src/OFSet.h ================================================================== --- src/OFSet.h +++ src/OFSet.h @@ -115,10 +115,17 @@ * @return A new, autoreleased set with the specified objects */ + (instancetype)setWithObjects: (ObjectType const _Nonnull *_Nonnull)objects count: (size_t)count; +/** + * @brief Initializes an already allocated set to be empty. + * + * @return An initialized set + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an already allocated set with the specified set. * * @param set The set to initialize the set with * @return An initialized set with the specified set @@ -158,11 +165,11 @@ * @param objects An array of objects for the set * @param count The number of objects in the specified array * @return An initialized set with the specified objects */ - (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects - count: (size_t)count; + count: (size_t)count OF_DESIGNATED_INITIALIZER; /** * @brief Returns an OFEnumerator to enumerate through all objects of the set. * * @return An OFEnumerator to enumerate through all objects of the set Index: src/OFSet.m ================================================================== --- src/OFSet.m +++ src/OFSet.m @@ -30,10 +30,16 @@ @interface OFPlaceholderSet: OFSet @end @implementation OFPlaceholderSet +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { return (id)[[OFConcreteSet alloc] init]; } @@ -69,10 +75,13 @@ - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { return (id)[[OFConcreteSet alloc] initWithObject: firstObject arguments: arguments]; } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif OF_SINGLETON_METHODS @end @implementation OFSet @@ -142,22 +151,74 @@ return [super init]; } - (instancetype)initWithSet: (OFSet *)set { - OF_INVALID_INIT_METHOD + id *objects = NULL; + size_t count; + + @try { + void *pool = objc_autoreleasePoolPush(); + size_t i = 0; + + count = set.count; + objects = OFAllocMemory(count, sizeof(id)); + + for (id object in set) { + OFEnsure(i < count); + objects[i++] = object; + } + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + OFFreeMemory(objects); + + [self release]; + @throw e; + } + + @try { + return [self initWithObjects: objects count: count]; + } @finally { + OFFreeMemory(objects); + } } - (instancetype)initWithArray: (OFArray *)array { - OF_INVALID_INIT_METHOD + void *pool = objc_autoreleasePoolPush(); + size_t count; + const id *objects; + + @try { + count = array.count; + objects = array.objects; + } @catch (id e) { + [self release]; + @throw e; + } + + self = [self initWithObjects: objects count: count]; + + objc_autoreleasePoolPop(pool); + + return self; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (instancetype)initWithObjects: (id)firstObject, ... { id ret; va_list arguments; @@ -169,11 +230,40 @@ return ret; } - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { - OF_INVALID_INIT_METHOD + size_t count = 1; + va_list argumentsCopy; + id *objects; + + if (firstObject == nil) + return [self init]; + + va_copy(argumentsCopy, arguments); + while (va_arg(argumentsCopy, id) != nil) + count++; + + @try { + objects = OFAllocMemory(count, sizeof(id)); + } @catch (id e) { + [self release]; + @throw e; + } + + @try { + objects[0] = firstObject; + + for (size_t i = 1; i < count; i++) { + objects[i] = va_arg(arguments, id); + OFEnsure(objects[i] != nil); + } + + return [self initWithObjects: objects count: count]; + } @finally { + OFFreeMemory(objects); + } } - (size_t)count { OF_UNRECOGNIZED_SELECTOR