Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -205,10 +205,11 @@ OFRectValue.m \ OFSandbox.m \ OFSizeValue.m \ OFStrPTime.m \ OFSubarray.m \ + OFSubdata.m \ OFUTF8String.m \ ${LIBBASES_M} \ ${RUNTIME_AUTORELEASE_M} \ ${RUNTIME_INSTANCE_M} \ ${UNICODE_M} Index: src/OFAdjacentArray.m ================================================================== --- src/OFAdjacentArray.m +++ src/OFAdjacentArray.m @@ -231,11 +231,12 @@ if ([self isKindOfClass: [OFMutableArray class]]) return [OFArray arrayWithObjects: (id *)_array.items + range.location count: range.length]; - return [OFAdjacentSubarray arrayWithArray: self range: range]; + return [[[OFAdjacentSubarray alloc] initWithArray: self + range: range] autorelease]; } - (bool)isEqual: (id)object { OFArray *otherArray; Index: src/OFAdjacentData.h ================================================================== --- src/OFAdjacentData.h +++ src/OFAdjacentData.h @@ -20,10 +20,9 @@ @interface OFAdjacentData: OFData { unsigned char *_Nullable _items; size_t _capacity, _count, _itemSize; bool _freeWhenDone; - OFData *_Nullable _parentData; } @end OF_ASSUME_NONNULL_END Index: src/OFAdjacentData.m ================================================================== --- src/OFAdjacentData.m +++ src/OFAdjacentData.m @@ -96,12 +96,10 @@ - (void)dealloc { if (_freeWhenDone) OFFreeMemory(_items); - [_parentData release]; - [super dealloc]; } - (size_t)count { @@ -115,24 +113,6 @@ - (const void *)items { return _items; } - -- (OFData *)subdataWithRange: (OFRange)range -{ - OFAdjacentData *ret; - - if (range.length > SIZE_MAX - range.location || - range.location + range.length > _count) - @throw [OFOutOfRangeException exception]; - - ret = [OFAdjacentData - dataWithItemsNoCopy: _items + (range.location * _itemSize) - count: range.length - itemSize: _itemSize - freeWhenDone: false]; - ret->_parentData = [(_parentData != nil ? _parentData : self) copy]; - - return ret; -} @end Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -363,11 +363,12 @@ if (range.length > SIZE_MAX - range.location || range.location + range.length < self.count) @throw [OFOutOfRangeException exception]; if (![self isKindOfClass: [OFMutableArray class]]) - return [OFSubarray arrayWithArray: self range: range]; + return [[[OFSubarray alloc] initWithArray: self + range: range] autorelease]; buffer = OFAllocMemory(range.length, sizeof(*buffer)); @try { [self getObjects: buffer inRange: range]; Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -29,10 +29,11 @@ #endif #import "OFIRI.h" #import "OFIRIHandler.h" #import "OFStream.h" #import "OFString.h" +#import "OFSubdata.h" #import "OFSystemInfo.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" @@ -561,21 +562,22 @@ return hash; } - (OFData *)subdataWithRange: (OFRange)range { - size_t itemSize; - if (range.length > SIZE_MAX - range.location || range.location + range.length > self.count) @throw [OFOutOfRangeException exception]; - itemSize = self.itemSize; + if (![self isKindOfClass: [OFMutableData class]]) + return [[[OFSubdata alloc] initWithData: self + range: range] autorelease]; + return [OFData dataWithItems: (const unsigned char *)self.items + - (range.location * itemSize) - count: range.length - itemSize: itemSize]; + (range.location * self.itemSize) + count: self.count + itemSize: self.itemSize]; } - (OFString *)description { OFMutableString *ret = [OFMutableString stringWithString: @"<"]; Index: src/OFMutableAdjacentData.h ================================================================== --- src/OFMutableAdjacentData.h +++ src/OFMutableAdjacentData.h @@ -20,10 +20,9 @@ @interface OFMutableAdjacentData: OFMutableData { unsigned char *_Nullable _items; size_t _capacity, _count, _itemSize; bool _freeWhenDone; - OFData *_Nullable _parentData; } @end OF_ASSUME_NONNULL_END Index: src/OFSubarray.h ================================================================== --- src/OFSubarray.h +++ src/OFSubarray.h @@ -21,10 +21,9 @@ { OFArray *_array; OFRange _range; } -+ (instancetype)arrayWithArray: (OFArray *)array range: (OFRange)range; - (instancetype)initWithArray: (OFArray *)array range: (OFRange)range; @end OF_ASSUME_NONNULL_END ADDED src/OFSubdata.h Index: src/OFSubdata.h ================================================================== --- src/OFSubdata.h +++ src/OFSubdata.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008-2023 Jonathan Schleifer + * + * 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. + */ + +#import "OFData.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFSubdata: OFData +{ + OFData *_data; + OFRange _range; +} + +- (instancetype)initWithData: (OFData *)data range: (OFRange)range; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFSubdata.m Index: src/OFSubdata.m ================================================================== --- src/OFSubdata.m +++ src/OFSubdata.m @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008-2023 Jonathan Schleifer + * + * 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 "OFSubdata.h" + +@implementation OFSubdata +- (instancetype)initWithData: (OFData *)data range: (OFRange)range +{ + self = [super init]; + + @try { + /* Should usually be retain, as it's useless with a copy */ + _data = [data copy]; + _range = range; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_data release]; + + [super dealloc]; +} + +- (size_t)count +{ + return _range.length; +} + +- (size_t)itemSize +{ + return _data.itemSize; +} + +- (const void *)items +{ + return (const unsigned char *)_data.items + + (_range.location * _data.itemSize); +} +@end