ObjFW  Check-in [91fa20d993]

Overview
Comment:Make OFData a class cluster
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 91fa20d993b9bba3795118e275134355607c75a6732810ea58c980a0dc4ae3ac
User & Date: js on 2023-08-07 18:20:48
Other Links: manifest | tags
References
2023-08-23
16:07 Fixed ticket [16dbdfcc5f]: Make OFData a class cluster plus 4 other changes artifact: c72b197265 user: js
Context
2023-08-07
20:59
Make GCC happy again check-in: 5f9d8d958b user: js tags: trunk
18:20
Make OFData a class cluster check-in: 91fa20d993 user: js tags: trunk
2023-08-06
10:24
Allow calling -[OFTimer fire] explicitly check-in: 7ab64323ef user: js tags: trunk
Changes

Modified src/Makefile from [b7c9d5d7ff] to [ee4f124e3c].

179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
	OFAdjacentSubarray.m		\
	OFArchiveIRIHandler.m		\
	OFBase64.m			\
	OFBitSetCharacterSet.m		\
	OFBytesValue.m			\
	OFCRC16.m			\
	OFCRC32.m			\

	OFCountedMapTableSet.m		\
	OFEmbeddedIRIHandler.m		\
	OFHuffmanTree.m			\
	OFINIFileSettings.m		\
	OFInvertedCharacterSet.m	\
	OFLHADecompressingStream.m	\
	OFMapTableDictionary.m		\
	OFMapTableSet.m			\
	OFMutableAdjacentArray.m	\

	OFMutableMapTableDictionary.m	\
	OFMutableMapTableSet.m		\
	OFMutableUTF8String.m		\
	OFNonretainedObjectValue.m	\
	OFPointValue.m			\
	OFPointerValue.m		\
	OFRangeCharacterSet.m		\







>









>







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
	OFAdjacentSubarray.m		\
	OFArchiveIRIHandler.m		\
	OFBase64.m			\
	OFBitSetCharacterSet.m		\
	OFBytesValue.m			\
	OFCRC16.m			\
	OFCRC32.m			\
	OFConcreteData.m		\
	OFCountedMapTableSet.m		\
	OFEmbeddedIRIHandler.m		\
	OFHuffmanTree.m			\
	OFINIFileSettings.m		\
	OFInvertedCharacterSet.m	\
	OFLHADecompressingStream.m	\
	OFMapTableDictionary.m		\
	OFMapTableSet.m			\
	OFMutableAdjacentArray.m	\
	OFMutableConcreteData.m		\
	OFMutableMapTableDictionary.m	\
	OFMutableMapTableSet.m		\
	OFMutableUTF8String.m		\
	OFNonretainedObjectValue.m	\
	OFPointValue.m			\
	OFPointerValue.m		\
	OFRangeCharacterSet.m		\

Added src/OFConcreteData.h version [7c0b340f55].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * 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.
 */

#import "OFData.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFConcreteData: OFData
{
	unsigned char *_Nullable _items;
	size_t _capacity, _count, _itemSize;
	bool _freeWhenDone;
	OFData *_Nullable _parentData;
}
@end

OF_ASSUME_NONNULL_END

Added src/OFConcreteData.m version [228c900b27].





















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * 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"

#include <limits.h>
#include <string.h>

#import "OFConcreteData.h"

#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

@implementation OFConcreteData
- (instancetype)init
{
	return [self initWithItemSize: 1];
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_itemSize = itemSize;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = OFAllocMemory(count, itemSize);
		_capacity = _count = count;
		_itemSize = itemSize;
		_freeWhenDone = true;

		memcpy(_items, items, count * itemSize);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = (unsigned char *)items;
		_capacity = _count = count;
		_itemSize = itemSize;
		_freeWhenDone = freeWhenDone;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	if (_freeWhenDone)
		OFFreeMemory(_items);

	[_parentData release];

	[super dealloc];
}

- (size_t)count
{
	return _count;
}

- (size_t)itemSize
{
	return _itemSize;
}

- (const void *)items
{
	return _items;
}

- (OFData *)subdataWithRange: (OFRange)range
{
	OFConcreteData *ret;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];

	ret = [OFConcreteData
	    dataWithItemsNoCopy: _items + (range.location * _itemSize)
			  count: range.length
		       itemSize: _itemSize
		   freeWhenDone: false];
	ret->_parentData = [(_parentData != nil ? _parentData : self) copy];

	return ret;
}
@end

Modified src/OFData+CryptographicHashing.m from [d27651b9f8] to [7ae571e356].

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	void *pool = objc_autoreleasePoolPush();
	id <OFCryptographicHash> hash =
	    [class hashWithAllowsSwappableMemory: true];
	size_t digestSize = [class digestSize];
	const unsigned char *digest;
	char cString[digestSize * 2];

	[hash updateWithBuffer: self->_items
			length: self->_count * self->_itemSize];
	[hash calculate];
	digest = hash.digest;

	for (size_t i = 0; i < digestSize; i++) {
		uint8_t high, low;

		high = digest[i] >> 4;







|
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	void *pool = objc_autoreleasePoolPush();
	id <OFCryptographicHash> hash =
	    [class hashWithAllowsSwappableMemory: true];
	size_t digestSize = [class digestSize];
	const unsigned char *digest;
	char cString[digestSize * 2];

	[hash updateWithBuffer: self.items
			length: self.count * self.itemSize];
	[hash calculate];
	digest = hash.digest;

	for (size_t i = 0; i < digestSize; i++) {
		uint8_t high, low;

		high = digest[i] >> 4;

Modified src/OFData.h from [c6b9b129b7] to [3b565bfb8e].

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
 * @class OFData OFData.h ObjFW/OFData.h
 *
 * @brief A class for storing arbitrary data in an array.
 */
@interface OFData: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFMessagePackRepresentation>
{
	unsigned char *_Nullable _items;
	size_t _count, _itemSize;
	bool _freeWhenDone;
@private
	OFData *_Nullable _parentData;
	OF_RESERVE_IVARS(OFData, 4)
}

/**
 * @brief The size of a single item in the OFData in bytes.
 */
@property (readonly, nonatomic) size_t itemSize;

/**
 * @brief The number of items in the OFData.







<
<
<
<
<
<
<
<
<







36
37
38
39
40
41
42









43
44
45
46
47
48
49
/**
 * @class OFData OFData.h ObjFW/OFData.h
 *
 * @brief A class for storing arbitrary data in an array.
 */
@interface OFData: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFMessagePackRepresentation>









/**
 * @brief The size of a single item in the OFData in bytes.
 */
@property (readonly, nonatomic) size_t itemSize;

/**
 * @brief The number of items in the OFData.
88
89
90
91
92
93
94















95
96
97
98
99
100
101
@property (readonly, nonatomic) OFString *stringRepresentation;

/**
 * @brief A string containing the data in Base64 encoding.
 */
@property (readonly, nonatomic) OFString *stringByBase64Encoding;
















/**
 * @brief Creates a new OFData with the specified `count` items of size 1.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @return A new autoreleased OFData
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
@property (readonly, nonatomic) OFString *stringRepresentation;

/**
 * @brief A string containing the data in Base64 encoding.
 */
@property (readonly, nonatomic) OFString *stringByBase64Encoding;

/**
 * @brief Creates a new OFData that is empty with an item size of 1.
 *
 * @return A new autoreleased OFData
 */
+ (instancetype)data;

/**
 * @brief Creates a new OFData that is empty with the specified item size.
 *
 * @param itemSize The size of a single element in the OFData
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithItemSize: (size_t)itemSize;

/**
 * @brief Creates a new OFData with the specified `count` items of size 1.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @return A new autoreleased OFData
 */
188
189
190
191
192
193
194

















195
196
197
198
199
200
201
 * @param string The string with the Base64-encoded data
 * @return A new autoreleased OFData
 * @throw OFInvalidFormatException The specified string is not correctly
 *				   formatted
 */
+ (instancetype)dataWithBase64EncodedString: (OFString *)string;


















/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of size 1.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @return An initialized OFData







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
 * @param string The string with the Base64-encoded data
 * @return A new autoreleased OFData
 * @throw OFInvalidFormatException The specified string is not correctly
 *				   formatted
 */
+ (instancetype)dataWithBase64EncodedString: (OFString *)string;

/**
 * @brief Initializes an already allocated OFData to be empty with an item size
 *	  of 1.
 *
 * @return An initialized OFData
 */
- (instancetype)init;

/**
 * @brief Initializes an already allocated OFData to be empty with the
 *	  specified item size.
 *
 * @param itemSize The size of a single element in the OFData
 * @return An initialized OFData
 */
- (instancetype)initWithItemSize: (size_t)itemSize;

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of size 1.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @return An initialized OFData

Modified src/OFData.m from [fedaecf95c] to [7bf8c0e585].

17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42







43
44
45
46
47
48
49
50





































































51





52

















53
54
55
56
57
58
59

#include <stdlib.h>
#include <string.h>
#include <limits.h>

#import "OFData.h"
#import "OFBase64.h"

#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFUnsupportedProtocolException.h"








/* References for static linking */
void
_references_to_categories_of_OFData(void)
{
	_OFData_CryptographicHashing_reference = 1;
	_OFData_MessagePackParsing_reference = 1;
}






































































@implementation OFData





@synthesize itemSize = _itemSize;


















+ (instancetype)dataWithItems: (const void *)items count: (size_t)count
{
	return [[[self alloc] initWithItems: items count: count] autorelease];
}

+ (instancetype)dataWithItems: (const void *)items







>



















>
>
>
>
>
>
>








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

#include <stdlib.h>
#include <string.h>
#include <limits.h>

#import "OFData.h"
#import "OFBase64.h"
#import "OFConcreteData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFUnsupportedProtocolException.h"

static struct {
	Class isa;
} placeholder;

@interface OFDataPlaceholder: OFString
@end

/* References for static linking */
void
_references_to_categories_of_OFData(void)
{
	_OFData_CryptographicHashing_reference = 1;
	_OFData_MessagePackParsing_reference = 1;
}

@implementation OFDataPlaceholder
- (instancetype)init
{
	return (id)[[OFConcreteData alloc] init];
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	return (id)[[OFConcreteData alloc] initWithItemSize: itemSize];
}

- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	return (id)[[OFConcreteData alloc] initWithItems: items count: count];
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	return (id)[[OFConcreteData alloc] initWithItems: items
						   count: count
						itemSize: itemSize];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	return (id)[[OFConcreteData alloc] initWithItemsNoCopy: items
							 count: count
						  freeWhenDone: freeWhenDone];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	return (id)[[OFConcreteData alloc] initWithItemsNoCopy: items
							 count: count
						      itemSize: itemSize
						  freeWhenDone: freeWhenDone];
}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	return (id)[[OFConcreteData alloc] initWithContentsOfFile: path];
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return (id)[[OFConcreteData alloc] initWithContentsOfIRI: IRI];
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	return (id)[[OFConcreteData alloc]
	    initWithStringRepresentation: string];
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{
	return (id)[[OFConcreteData alloc] initWithBase64EncodedString: string];
}
@end

@implementation OFData
+ (void)initialize
{
	if (self == [OFData class])
		placeholder.isa = [OFDataPlaceholder class];
}

+ (instancetype)alloc
{
	if (self == [OFData class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)data
{
	return [[[self alloc] init] autorelease];
}

+ (instancetype)dataWithItemSize: (size_t)itemSize
{
	return [[[self alloc] initWithItemSize: itemSize] autorelease];
}

+ (instancetype)dataWithItems: (const void *)items count: (size_t)count
{
	return [[[self alloc] initWithItems: items count: count] autorelease];
}

+ (instancetype)dataWithItems: (const void *)items
103
104
105
106
107
108
109





















110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
	    initWithStringRepresentation: string] autorelease];
}

+ (instancetype)dataWithBase64EncodedString: (OFString *)string
{
	return [[[self alloc] initWithBase64EncodedString: string] autorelease];
}






















- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	return [self initWithItems: items count: count itemSize: 1];
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = OFAllocMemory(count, itemSize);
		_count = count;
		_itemSize = itemSize;
		_freeWhenDone = true;

		memcpy(_items, items, count * itemSize);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	return [self initWithItemsNoCopy: items
				   count: count
				itemSize: 1
			    freeWhenDone: freeWhenDone];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = (unsigned char *)items;
		_count = count;
		_itemSize = itemSize;
		_freeWhenDone = freeWhenDone;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	char *buffer = NULL;
	OFStreamOffset fileSize;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

















<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

240
















241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

258














259
260
261
262
263
264
265
	    initWithStringRepresentation: string] autorelease];
}

+ (instancetype)dataWithBase64EncodedString: (OFString *)string
{
	return [[[self alloc] initWithBase64EncodedString: string] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFString class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	return [self initWithItems: items count: count itemSize: 1];
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{

	OF_INVALID_INIT_METHOD
















}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	return [self initWithItemsNoCopy: items
				   count: count
				itemSize: 1
			    freeWhenDone: freeWhenDone];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{

	OF_INVALID_INIT_METHOD














}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	char *buffer = NULL;
	OFStreamOffset fileSize;
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250


251










252
253
254
255
256
257
258
259

260
261
262


263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282

	return self;
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{

	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFStream *stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];
		size_t pageSize;
		unsigned char *buffer;

		_count = 0;
		_itemSize = 1;
		_freeWhenDone = true;

		pageSize = [OFSystemInfo pageSize];
		buffer = OFAllocMemory(1, pageSize);

		@try {
			while (!stream.atEndOfStream) {
				size_t length = [stream
				    readIntoBuffer: buffer
					    length: pageSize];

				if (SIZE_MAX - _count < length)
					@throw [OFOutOfRangeException
					    exception];

				_items = OFResizeMemory(_items,
				    _count + length, 1);
				memcpy(_items + _count, buffer, length);
				_count += length;
			}
		} @finally {
			OFFreeMemory(buffer);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {


		[self release];










		@throw e;
	}

	return self;
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{

	self = [super init];

	@try {


		size_t count = [string
		    cStringLengthWithEncoding: OFStringEncodingASCII];
		const char *cString;

		if (count % 2 != 0)
			@throw [OFInvalidFormatException exception];

		count /= 2;

		_items = OFAllocMemory(count, 1);
		_count = count;
		_itemSize = 1;
		_freeWhenDone = true;

		cString = [string cStringWithEncoding: OFStringEncodingASCII];

		for (size_t i = 0; i < count; i++) {
			uint8_t c1 = cString[2 * i];
			uint8_t c2 = cString[2 * i + 1];
			uint8_t byte;







>
|





<

<
<
<
<



<
|
|
<
|

|
|
<

|
<
|
|
<
<
<




>
>

>
>
>
>
>
>
>
>
>
>








>
|


>
>
|

<





<
|
<
<
<







296
297
298
299
300
301
302
303
304
305
306
307
308
309

310




311
312
313

314
315

316
317
318
319

320
321

322
323



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

357
358
359
360
361

362



363
364
365
366
367
368
369

	return self;
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	char *items = NULL, *buffer = NULL;
	size_t count = 0;

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFStream *stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];
		size_t pageSize;






		pageSize = [OFSystemInfo pageSize];
		buffer = OFAllocMemory(1, pageSize);


		while (!stream.atEndOfStream) {
			size_t length = [stream readIntoBuffer: buffer

							length: pageSize];

			if (SIZE_MAX - count < length)
				@throw [OFOutOfRangeException exception];


			items = OFResizeMemory(items, count + length, 1);

			memcpy(items + count, buffer, length);
			count += length;



		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		OFFreeMemory(buffer);
		OFFreeMemory(items);
		[self release];

		@throw e;
	}

	@try {
		self = [self initWithItemsNoCopy: items
					   count: count
				    freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(items);
		@throw e;
	}

	return self;
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	char *items = NULL;
	size_t count = 0;

	@try {
		const char *cString;

		count = [string
		    cStringLengthWithEncoding: OFStringEncodingASCII];


		if (count % 2 != 0)
			@throw [OFInvalidFormatException exception];

		count /= 2;

		items = OFAllocMemory(count, 1);




		cString = [string cStringWithEncoding: OFStringEncodingASCII];

		for (size_t i = 0; i < count; i++) {
			uint8_t c1 = cString[2 * i];
			uint8_t c2 = cString[2 * i + 1];
			uint8_t byte;
295
296
297
298
299
300
301
302
303
304

305










306
307
308
309
310
311
312
			else if (c2 >= 'a' && c2 <= 'f')
				byte |= c2 - 'a' + 10;
			else if (c2 >= 'A' && c2 <= 'F')
				byte |= c2 - 'A' + 10;
			else
				@throw [OFInvalidFormatException exception];

			_items[i] = byte;
		}
	} @catch (id e) {

		[self release];










		@throw e;
	}

	return self;
}

- (instancetype)initWithBase64EncodedString: (OFString *)string







|


>

>
>
>
>
>
>
>
>
>
>







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
			else if (c2 >= 'a' && c2 <= 'f')
				byte |= c2 - 'a' + 10;
			else if (c2 >= 'A' && c2 <= 'F')
				byte |= c2 - 'A' + 10;
			else
				@throw [OFInvalidFormatException exception];

			items[i] = byte;
		}
	} @catch (id e) {
		OFFreeMemory(items);
		[self release];

		@throw e;
	}

	@try {
		self = [self initWithItemsNoCopy: items
					   count: count
				    freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(items);
		@throw e;
	}

	return self;
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368


369
370
371
372
373
374
375
376



377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404


405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446


447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466


467
468
469
470
471
472
473
474
475
476
477
478


479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496


497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514


515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582


583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

	if (!mutable)
		[(OFMutableData *)self makeImmutable];

	return self;
}

- (void)dealloc
{
	if (_freeWhenDone)
		OFFreeMemory(_items);

	[_parentData release];

	[super dealloc];
}

- (size_t)count
{
	return _count;

}

- (const void *)items
{
	return _items;
}

- (const void *)itemAtIndex: (size_t)idx
{
	if (idx >= _count)
		@throw [OFOutOfRangeException exception];

	return _items + idx * _itemSize;
}

- (const void *)firstItem
{


	if (_items == NULL || _count == 0)
		return NULL;

	return _items;
}

- (const void *)lastItem
{



	if (_items == NULL || _count == 0)
		return NULL;

	return _items + (_count - 1) * _itemSize;
}

- (id)copy
{
	return [self retain];
}

- (id)mutableCopy
{
	return [[OFMutableData alloc] initWithItems: _items
					      count: _count
					   itemSize: _itemSize];
}

- (bool)isEqual: (id)object
{

	OFData *data;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFData class]])
		return false;



	data = object;

	if (data.count != _count || data.itemSize != _itemSize)
		return false;
	if (memcmp(data.items, _items, _count * _itemSize) != 0)
		return false;

	return true;
}

- (OFComparisonResult)compare: (OFData *)data
{
	int comparison;
	size_t count, minCount;

	if (![data isKindOfClass: [OFData class]])
		@throw [OFInvalidArgumentException exception];

	if (data.itemSize != _itemSize)
		@throw [OFInvalidArgumentException exception];


	count = data.count;
	minCount = (_count > count ? count : _count);

	if ((comparison = memcmp(_items, data.items,
	    minCount * _itemSize)) == 0) {
		if (_count > count)
			return OFOrderedDescending;
		if (_count < count)
			return OFOrderedAscending;

		return OFOrderedSame;
	}

	if (comparison > 0)
		return OFOrderedDescending;
	else
		return OFOrderedAscending;
}

- (unsigned long)hash
{


	unsigned long hash;

	OFHashInit(&hash);

	for (size_t i = 0; i < _count * _itemSize; i++)
		OFHashAddByte(&hash, ((uint8_t *)_items)[i]);

	OFHashFinalize(&hash);

	return hash;
}

- (OFData *)subdataWithRange: (OFRange)range
{
	OFData *ret;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];



	ret = [OFData dataWithItemsNoCopy: _items + (range.location * _itemSize)
				    count: range.length
				 itemSize: _itemSize
			     freeWhenDone: false];
	ret->_parentData = [(_parentData != nil ? _parentData : self) copy];

	return ret;
}

- (OFString *)description
{
	OFMutableString *ret = [OFMutableString stringWithString: @"<"];



	for (size_t i = 0; i < _count; i++) {
		if (i > 0)
			[ret appendString: @" "];

		for (size_t j = 0; j < _itemSize; j++)
			[ret appendFormat: @"%02x", _items[i * _itemSize + j]];
	}

	[ret appendString: @">"];

	[ret makeImmutable];
	return ret;
}

- (OFString *)stringRepresentation
{
	OFMutableString *ret = [OFMutableString string];



	for (size_t i = 0; i < _count; i++)
		for (size_t j = 0; j < _itemSize; j++)
			[ret appendFormat: @"%02x", _items[i * _itemSize + j]];

	[ret makeImmutable];
	return ret;
}

- (OFString *)stringByBase64Encoding
{
	return OFBase64Encode(_items, _count * _itemSize);
}

- (OFRange)rangeOfData: (OFData *)data
	       options: (OFDataSearchOptions)options
		 range: (OFRange)range
{


	const char *search;
	size_t searchLength;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];

	if (data == nil || data.itemSize != _itemSize)
		@throw [OFInvalidArgumentException exception];

	if ((searchLength = data.count) == 0)
		return OFMakeRange(0, 0);

	if (searchLength > range.length)
		return OFMakeRange(OFNotFound, 0);

	search = data.items;

	if (options & OFDataSearchBackwards) {
		for (size_t i = range.length - searchLength;; i--) {
			if (memcmp(_items + i * _itemSize, search,
			    searchLength * _itemSize) == 0)
				return OFMakeRange(i, searchLength);

			/* No match and we're at the last item */
			if (i == 0)
				break;
		}
	} else {
		for (size_t i = range.location;
		    i <= range.length - searchLength; i++)
			if (memcmp(_items + i * _itemSize, search,
			    searchLength * _itemSize) == 0)
				return OFMakeRange(i, searchLength);
	}

	return OFMakeRange(OFNotFound, 0);
}

#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path
{
	OFFile *file = [[OFFile alloc] initWithPath: path mode: @"w"];
	@try {
		[file writeBuffer: _items length: _count * _itemSize];

	} @finally {
		[file release];
	}
}
#endif

- (void)writeToIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();

	[[OFIRIHandler openItemAtIRI: IRI mode: @"w"] writeData: self];

	objc_autoreleasePoolPop(pool);
}

- (OFData *)messagePackRepresentation
{
	OFMutableData *data;


	if (_itemSize != 1)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];



	if (_count <= UINT8_MAX) {
		uint8_t type = 0xC4;
		uint8_t tmp = (uint8_t)_count;

		data = [OFMutableData dataWithCapacity: _count + 2];
		[data addItem: &type];
		[data addItem: &tmp];
	} else if (_count <= UINT16_MAX) {
		uint8_t type = 0xC5;
		uint16_t tmp = OFToBigEndian16((uint16_t)_count);

		data = [OFMutableData dataWithCapacity: _count + 3];
		[data addItem: &type];
		[data addItems: &tmp count: sizeof(tmp)];
	} else if (_count <= UINT32_MAX) {
		uint8_t type = 0xC6;
		uint32_t tmp = OFToBigEndian32((uint32_t)_count);

		data = [OFMutableData dataWithCapacity: _count + 5];
		[data addItem: &type];
		[data addItems: &tmp count: sizeof(tmp)];
	} else
		@throw [OFOutOfRangeException exception];

	[data addItems: _items count: _count];
	[data makeImmutable];

	return data;
}
@end







|

<
<
|
<
|
<
|
<
|

<
>




|




|


|




>
>
|


|




>
>
>
|


|









|
|
|




>








>
>


|

|








|




|


>
|
|

|
|
|

|













>
>




|
|








|


|


>
>
|
|
|
<
<
<
<





>
>

|



|
|











>
>

|
|
|







|






>
>




|


|












|
|









|
|











|
>


















>

|



>
>
|

|

|


|

|

|


|

|

|





|





430
431
432
433
434
435
436
437
438


439

440

441

442
443

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575




576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724

	if (!mutable)
		[(OFMutableData *)self makeImmutable];

	return self;
}

- (size_t)count
{


	OF_UNRECOGNIZED_SELECTOR

}



- (size_t)itemSize
{

	OF_UNRECOGNIZED_SELECTOR
}

- (const void *)items
{
	OF_UNRECOGNIZED_SELECTOR
}

- (const void *)itemAtIndex: (size_t)idx
{
	if (idx >= self.count)
		@throw [OFOutOfRangeException exception];

	return (const unsigned char *)self.items + idx * self.itemSize;
}

- (const void *)firstItem
{
	const void *items = self.items;

	if (items == NULL || self.count == 0)
		return NULL;

	return items;
}

- (const void *)lastItem
{
	const unsigned char *items = self.items;
	size_t count = self.count;

	if (items == NULL || count == 0)
		return NULL;

	return items + (count - 1) * self.itemSize;
}

- (id)copy
{
	return [self retain];
}

- (id)mutableCopy
{
	return [[OFMutableData alloc] initWithItems: self.items
					      count: self.count
					   itemSize: self.itemSize];
}

- (bool)isEqual: (id)object
{
	size_t count, itemSize;
	OFData *data;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFData class]])
		return false;

	count = self.count;
	itemSize = self.itemSize;
	data = object;

	if (data.count != count || data.itemSize != itemSize)
		return false;
	if (memcmp(data.items, self.items, count * itemSize) != 0)
		return false;

	return true;
}

- (OFComparisonResult)compare: (OFData *)data
{
	int comparison;
	size_t count, dataCount, minCount;

	if (![data isKindOfClass: [OFData class]])
		@throw [OFInvalidArgumentException exception];

	if (data.itemSize != self.itemSize)
		@throw [OFInvalidArgumentException exception];

	count = self.count;
	dataCount = data.count;
	minCount = (count > dataCount ? dataCount : count);

	if ((comparison = memcmp(self.items, data.items,
	    minCount * self.itemSize)) == 0) {
		if (count > dataCount)
			return OFOrderedDescending;
		if (count < dataCount)
			return OFOrderedAscending;

		return OFOrderedSame;
	}

	if (comparison > 0)
		return OFOrderedDescending;
	else
		return OFOrderedAscending;
}

- (unsigned long)hash
{
	const unsigned char *items = self.items;
	size_t count = self.count, itemSize = self.itemSize;
	unsigned long hash;

	OFHashInit(&hash);

	for (size_t i = 0; i < count * itemSize; i++)
		OFHashAddByte(&hash, items[i]);

	OFHashFinalize(&hash);

	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;
	return [OFData dataWithItems: (const unsigned char *)self.items +
				      (range.location * itemSize)
			       count: range.length
			    itemSize: itemSize];




}

- (OFString *)description
{
	OFMutableString *ret = [OFMutableString stringWithString: @"<"];
	const unsigned char *items = self.items;
	size_t count = self.count, itemSize = self.itemSize;

	for (size_t i = 0; i < count; i++) {
		if (i > 0)
			[ret appendString: @" "];

		for (size_t j = 0; j < itemSize; j++)
			[ret appendFormat: @"%02x", items[i * itemSize + j]];
	}

	[ret appendString: @">"];

	[ret makeImmutable];
	return ret;
}

- (OFString *)stringRepresentation
{
	OFMutableString *ret = [OFMutableString string];
	const unsigned char *items = self.items;
	size_t count = self.count, itemSize = self.itemSize;

	for (size_t i = 0; i < count; i++)
		for (size_t j = 0; j < itemSize; j++)
			[ret appendFormat: @"%02x", items[i * itemSize + j]];

	[ret makeImmutable];
	return ret;
}

- (OFString *)stringByBase64Encoding
{
	return OFBase64Encode(self.items, self.count * self.itemSize);
}

- (OFRange)rangeOfData: (OFData *)data
	       options: (OFDataSearchOptions)options
		 range: (OFRange)range
{
	const unsigned char *items = self.items;
	size_t count = self.count, itemSize = self.itemSize;
	const char *search;
	size_t searchLength;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > count)
		@throw [OFOutOfRangeException exception];

	if (data == nil || data.itemSize != itemSize)
		@throw [OFInvalidArgumentException exception];

	if ((searchLength = data.count) == 0)
		return OFMakeRange(0, 0);

	if (searchLength > range.length)
		return OFMakeRange(OFNotFound, 0);

	search = data.items;

	if (options & OFDataSearchBackwards) {
		for (size_t i = range.length - searchLength;; i--) {
			if (memcmp(items + i * itemSize, search,
			    searchLength * itemSize) == 0)
				return OFMakeRange(i, searchLength);

			/* No match and we're at the last item */
			if (i == 0)
				break;
		}
	} else {
		for (size_t i = range.location;
		    i <= range.length - searchLength; i++)
			if (memcmp(items + i * itemSize, search,
			    searchLength * itemSize) == 0)
				return OFMakeRange(i, searchLength);
	}

	return OFMakeRange(OFNotFound, 0);
}

#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path
{
	OFFile *file = [[OFFile alloc] initWithPath: path mode: @"w"];
	@try {
		[file writeBuffer: self.items
			   length: self.count * self.itemSize];
	} @finally {
		[file release];
	}
}
#endif

- (void)writeToIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();

	[[OFIRIHandler openItemAtIRI: IRI mode: @"w"] writeData: self];

	objc_autoreleasePoolPop(pool);
}

- (OFData *)messagePackRepresentation
{
	OFMutableData *data;
	size_t count;

	if (self.itemSize != 1)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	count = self.count;

	if (count <= UINT8_MAX) {
		uint8_t type = 0xC4;
		uint8_t tmp = (uint8_t)count;

		data = [OFMutableData dataWithCapacity: count + 2];
		[data addItem: &type];
		[data addItem: &tmp];
	} else if (count <= UINT16_MAX) {
		uint8_t type = 0xC5;
		uint16_t tmp = OFToBigEndian16((uint16_t)count);

		data = [OFMutableData dataWithCapacity: count + 3];
		[data addItem: &type];
		[data addItems: &tmp count: sizeof(tmp)];
	} else if (count <= UINT32_MAX) {
		uint8_t type = 0xC6;
		uint32_t tmp = OFToBigEndian32((uint32_t)count);

		data = [OFMutableData dataWithCapacity: count + 5];
		[data addItem: &type];
		[data addItems: &tmp count: sizeof(tmp)];
	} else
		@throw [OFOutOfRangeException exception];

	[data addItems: self.items count: count];
	[data makeImmutable];

	return data;
}
@end

Added src/OFMutableConcreteData.h version [2a0d338a69].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * 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.
 */

#import "OFMutableData.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFMutableConcreteData: OFMutableData
{
	unsigned char *_Nullable _items;
	size_t _capacity, _count, _itemSize;
	bool _freeWhenDone;
	OFData *_Nullable _parentData;
}
@end

OF_ASSUME_NONNULL_END

Added src/OFMutableConcreteData.m version [bbba29f5a7].



























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
 * 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"

#include <limits.h>
#include <string.h>

#import "OFMutableConcreteData.h"
#import "OFConcreteData.h"

#import "OFInvalidArgumentException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"

@implementation OFMutableConcreteData
+ (void)initialize
{
	if (self == [OFMutableConcreteData class])
		[self inheritMethodsFromClass: [OFConcreteData class]];
}

- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = OFAllocMemory(capacity, itemSize);
		_itemSize = itemSize;
		_capacity = capacity;
		_freeWhenDone = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [self initWithItems: items count: count itemSize: itemSize];

	if (freeWhenDone)
		OFFreeMemory(items);

	return self;
}

- (void *)mutableItems
{
	return _items;
}

- (void)addItem: (const void *)item
{
	if (SIZE_MAX - _count < 1)
		@throw [OFOutOfRangeException exception];

	if (_count + 1 > _capacity) {
		_items = OFResizeMemory(_items, _count + 1, _itemSize);
		_capacity = _count + 1;
	}

	memcpy(_items + _count * _itemSize, item, _itemSize);

	_count++;
}

- (void)addItems: (const void *)items count: (size_t)count
{
	if (count > SIZE_MAX - _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memcpy(_items + _count * _itemSize, items, count * _itemSize);
	_count += count;
}

- (void)insertItems: (const void *)items
	    atIndex: (size_t)idx
	      count: (size_t)count
{
	if (count > SIZE_MAX - _count || idx > _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memmove(_items + (idx + count) * _itemSize, _items + idx * _itemSize,
	    (_count - idx) * _itemSize);
	memcpy(_items + idx * _itemSize, items, count * _itemSize);

	_count += count;
}

- (void)increaseCountBy: (size_t)count
{
	if (count > SIZE_MAX - _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memset(_items + _count * _itemSize, '\0', count * _itemSize);
	_count += count;
}

- (void)removeItemsInRange: (OFRange)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];

	memmove(_items + range.location * _itemSize,
	    _items + (range.location + range.length) * _itemSize,
	    (_count - range.location - range.length) * _itemSize);

	_count -= range.length;
	@try {
		_items = OFResizeMemory(_items, _count, _itemSize);
		_capacity = _count;
	} @catch (OFOutOfMemoryException *e) {
		/* We don't really care, as we only made it smaller */
	}
}

- (void)removeLastItem
{
	if (_count == 0)
		return;

	_count--;
	@try {
		_items = OFResizeMemory(_items, _count, _itemSize);
		_capacity = _count;
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only made it smaller */
	}
}

- (void)removeAllItems
{
	OFFreeMemory(_items);
	_items = NULL;
	_count = 0;
	_capacity = 0;
}

- (void)makeImmutable
{
	if (_capacity != _count) {
		@try {
			_items = OFResizeMemory(_items, _count, _itemSize);
			_capacity = _count;
		} @catch (OFOutOfMemoryException *e) {
			/* We don't care, as we only made it smaller */
		}
	}

	object_setClass(self, [OFConcreteData class]);
}
@end

Modified src/OFMutableData.h from [6167546110] to [4756340133].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 * file.
 */

#import "OFData.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;

/**
 * @class OFMutableData OFMutableData.h ObjFW/OFMutableData.h
 *
 * @brief A class for storing and manipulating arbitrary data in an array.
 */
@interface OFMutableData: OFData
{
	size_t _capacity;
	OF_RESERVE_IVARS(OFMutableData, 4)
}

/**
 * @brief All items of the OFMutableData as a C array.
 *
 * @warning The pointer is only valid until the OFMutableData is changed!
 *
 * Modifying the returned array directly is allowed and will change the contents
 * of the data.







<
<






<
<
<
<
<







13
14
15
16
17
18
19


20
21
22
23
24
25





26
27
28
29
30
31
32
 * file.
 */

#import "OFData.h"

OF_ASSUME_NONNULL_BEGIN



/**
 * @class OFMutableData OFMutableData.h ObjFW/OFMutableData.h
 *
 * @brief A class for storing and manipulating arbitrary data in an array.
 */
@interface OFMutableData: OFData





/**
 * @brief All items of the OFMutableData as a C array.
 *
 * @warning The pointer is only valid until the OFMutableData is changed!
 *
 * Modifying the returned array directly is allowed and will change the contents
 * of the data.
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

/**
 * @brief The last item of the OFMutableData or `NULL`.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *mutableLastItem
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Creates a new OFMutableData with an item size of 1.
 *
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)data;

/**
 * @brief Creates a new OFMutableData whose items all have the same specified
 *	  size.
 *
 * @param itemSize The size of a single element in the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithItemSize: (size_t)itemSize;

/**
 * @brief Creates a new OFMutableData with enough memory to hold the specified
 *	  number of items which all have an item size of 1.
 *
 * @param capacity The initial capacity for the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithCapacity: (size_t)capacity;

/**
 * @brief Creates a new OFMutableData with enough memory to hold the specified
 *	  number of items which all have the same specified size.
 *
 * @param itemSize The size of a single element in the OFMutableData
 * @param capacity The initial capacity for the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity;

/**
 * @brief Initializes an already allocated OFMutableData with an item size of 1.
 *
 * @return An initialized OFMutableData
 */
- (instancetype)init;

/**
 * @brief Initializes an already allocated OFMutableData whose items all have
 *	  the same size.
 *
 * @param itemSize The size of a single element in the OFMutableData
 * @return An initialized OFMutableData
 */
- (instancetype)initWithItemSize: (size_t)itemSize;

/**
 * @brief Initializes an already allocated OFMutableData with enough memory to
 *	  hold the the specified number of items which all have an item size of
 *	  1.
 *
 * @param capacity The initial capacity for the OFMutableData
 * @return An initialized OFMutableData







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







42
43
44
45
46
47
48
















49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
















68
69
70
71
72
73
74

/**
 * @brief The last item of the OFMutableData or `NULL`.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *mutableLastItem
    OF_RETURNS_INNER_POINTER;

















/**
 * @brief Creates a new OFMutableData with enough memory to hold the specified
 *	  number of items which all have an item size of 1.
 *
 * @param capacity The initial capacity for the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithCapacity: (size_t)capacity;

/**
 * @brief Creates a new OFMutableData with enough memory to hold the specified
 *	  number of items which all have the same specified size.
 *
 * @param itemSize The size of a single element in the OFMutableData
 * @param capacity The initial capacity for the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity;

















/**
 * @brief Initializes an already allocated OFMutableData with enough memory to
 *	  hold the the specified number of items which all have an item size of
 *	  1.
 *
 * @param capacity The initial capacity for the OFMutableData
 * @return An initialized OFMutableData

Modified src/OFMutableData.m from [ab7e0d2674] to [fb095843a4].

16
17
18
19
20
21
22
23
24
25
26
27
28



























































































29






30
31


32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152

153

154
155
156
157
158
159
160



161
162
163
164
165
166
167
168


169
170
171
172

173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <limits.h>

#import "OFMutableData.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"




























































































@implementation OFMutableData






+ (instancetype)data
{


	return [[[self alloc] init] autorelease];

}

+ (instancetype)dataWithItemSize: (size_t)itemSize
{
	return [[[self alloc] initWithItemSize: itemSize] autorelease];
}

+ (instancetype)dataWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

+ (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	return [[[self alloc] initWithItemSize: itemSize
				      capacity: capacity] autorelease];
}

- (instancetype)init
{
	self = [super init];

	_itemSize = 1;
	_freeWhenDone = true;

	return self;
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_itemSize = itemSize;
		_freeWhenDone = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return [self initWithItemSize: 1
			     capacity: capacity];
}

- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = OFAllocMemory(capacity, itemSize);
		_itemSize = itemSize;
		_capacity = capacity;
		_freeWhenDone = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	self = [super initWithItems: items count: count itemSize: itemSize];

	_capacity = _count;

	return self;
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [self initWithItems: items count: count itemSize: itemSize];

	if (freeWhenDone)
		OFFreeMemory(items);

	return self;
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	self = [super initWithStringRepresentation: string];

	_capacity = _count;

	return self;
}

- (void *)mutableItems
{
	return _items;

}

- (void *)mutableItemAtIndex: (size_t)idx
{
	if (idx >= _count)
		@throw [OFOutOfRangeException exception];

	return _items + idx * _itemSize;
}

- (void *)mutableFirstItem
{

	if (_items == NULL || _count == 0)

		return NULL;

	return _items;
}

- (void *)mutableLastItem
{



	if (_items == NULL || _count == 0)
		return NULL;

	return _items + (_count - 1) * _itemSize;
}

- (OFData *)subdataWithRange: (OFRange)range
{


	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];


	return [OFData dataWithItems: _items + (range.location * _itemSize)

			       count: range.length
			    itemSize: _itemSize];
}

- (void)addItem: (const void *)item
{
	if (SIZE_MAX - _count < 1)
		@throw [OFOutOfRangeException exception];

	if (_count + 1 > _capacity) {
		_items = OFResizeMemory(_items, _count + 1, _itemSize);
		_capacity = _count + 1;
	}

	memcpy(_items + _count * _itemSize, item, _itemSize);

	_count++;
}

- (void)insertItem: (const void *)item atIndex: (size_t)idx
{
	[self insertItems: item atIndex: idx count: 1];
}

- (void)addItems: (const void *)items count: (size_t)count
{
	if (count > SIZE_MAX - _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memcpy(_items + _count * _itemSize, items, count * _itemSize);
	_count += count;
}

- (void)insertItems: (const void *)items
	    atIndex: (size_t)idx
	      count: (size_t)count
{
	if (count > SIZE_MAX - _count || idx > _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memmove(_items + (idx + count) * _itemSize, _items + idx * _itemSize,
	    (_count - idx) * _itemSize);
	memcpy(_items + idx * _itemSize, items, count * _itemSize);

	_count += count;
}

- (void)increaseCountBy: (size_t)count
{
	if (count > SIZE_MAX - _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memset(_items + _count * _itemSize, '\0', count * _itemSize);
	_count += count;
}

- (void)removeItemAtIndex: (size_t)idx
{
	[self removeItemsInRange: OFMakeRange(idx, 1)];
}

- (void)removeItemsInRange: (OFRange)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];

	memmove(_items + range.location * _itemSize,
	    _items + (range.location + range.length) * _itemSize,
	    (_count - range.location - range.length) * _itemSize);

	_count -= range.length;
	@try {
		_items = OFResizeMemory(_items, _count, _itemSize);
		_capacity = _count;
	} @catch (OFOutOfMemoryException *e) {
		/* We don't really care, as we only made it smaller */
	}
}

- (void)removeLastItem
{
	if (_count == 0)
		return;

	_count--;
	@try {
		_items = OFResizeMemory(_items, _count, _itemSize);
		_capacity = _count;
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only made it smaller */
	}

}

- (void)removeAllItems
{
	OFFreeMemory(_items);
	_items = NULL;
	_count = 0;
	_capacity = 0;
}

- (id)copy
{
	return [[OFData alloc] initWithItems: _items
				       count: _count
				    itemSize: _itemSize];
}

- (void)makeImmutable
{
	if (_capacity != _count) {
		@try {
			_items = OFResizeMemory(_items, _count, _itemSize);
			_capacity = _count;
		} @catch (OFOutOfMemoryException *e) {
			/* We don't care, as we only made it smaller */
		}
	}

	object_setClass(self, [OFData class]);
}
@end







|

<
<


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
|

>
>
|
>


















<
<
<
<
<
<
<
<
<
<


<
<
<
<
<
<
<
<
<
<
<
<
<
|




|
<




<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<















<
<
<
<
<
<
<
<
<


<
>




|


|




>
|
>


|




>
>
>
|


|




>
>

|


>
|
>

|




<
<
|
<
<
<
<
<
<
<
<









<
<
|
<
<
<
<
<
<
<






<
<
|
<
<
<
<
<
<
<
<
<
<




<
<
|
<
<
<
<
<
<
<









<
<
<
|
<
<
<
<
<
<
<
<
<
<
<




|
<

|
|
<
<
<
<
|
>




<
<
|
<




|
|
|




<
<
<
<
<
<
|
<
<
<
<

16
17
18
19
20
21
22
23
24


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148










149
150













151
152
153
154
155
156

157
158
159
160

161

























162
163
164
165
166
167
168
169
170
171
172
173
174
175
176









177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227


228








229
230
231
232
233
234
235
236
237


238







239
240
241
242
243
244


245










246
247
248
249


250







251
252
253
254
255
256
257
258
259



260











261
262
263
264
265

266
267
268




269
270
271
272
273
274


275

276
277
278
279
280
281
282
283
284
285
286






287




288
#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <limits.h>

#import "OFMutableData.h"
#import "OFMutableConcreteData.h"



#import "OFOutOfRangeException.h"

static struct {
	Class isa;
} placeholder;

@interface OFMutableDataPlaceholder: OFMutableData
@end

@implementation OFMutableDataPlaceholder
- (instancetype)init
{
	return (id)[[OFMutableConcreteData alloc] init];
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	return (id)[[OFMutableConcreteData alloc] initWithItemSize: itemSize];
}

- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	return (id)[[OFMutableConcreteData alloc] initWithItems: items
							  count: count];
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	return (id)[[OFMutableConcreteData alloc] initWithItems: items
							  count: count
						       itemSize: itemSize];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	return (id)[[OFMutableConcreteData alloc]
	    initWithItemsNoCopy: items
			  count: count
		   freeWhenDone: freeWhenDone];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	return (id)[[OFMutableConcreteData alloc]
	    initWithItemsNoCopy: items
			  count: count
		       itemSize: itemSize
		   freeWhenDone: freeWhenDone];
}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	return (id)[[OFMutableConcreteData alloc] initWithContentsOfFile: path];
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return (id)[[OFMutableConcreteData alloc] initWithContentsOfIRI: IRI];
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	return (id)[[OFMutableConcreteData alloc]
	    initWithStringRepresentation: string];
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{
	return (id)[[OFMutableConcreteData alloc]
	    initWithBase64EncodedString: string];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFMutableConcreteData alloc] initWithCapacity: capacity];
}

- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	return (id)[[OFMutableConcreteData alloc] initWithItemSize: itemSize
							  capacity: capacity];
}
@end

@implementation OFMutableData
+ (void)initialize
{
	if (self == [OFMutableData class])
		placeholder.isa = [OFMutableDataPlaceholder class];
}

+ (instancetype)alloc
{
	if (self == [OFMutableData class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)dataWithItemSize: (size_t)itemSize
{
	return [[[self alloc] initWithItemSize: itemSize] autorelease];
}

+ (instancetype)dataWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

+ (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	return [[[self alloc] initWithItemSize: itemSize
				      capacity: capacity] autorelease];
}











- (instancetype)initWithItemSize: (size_t)itemSize
{













	return [self initWithItemSize: 1 capacity: 0];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return [self initWithItemSize: 1 capacity: capacity];

}

- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{

	OF_INVALID_INIT_METHOD

























}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [self initWithItems: items count: count itemSize: itemSize];

	if (freeWhenDone)
		OFFreeMemory(items);

	return self;
}










- (void *)mutableItems
{

	OF_UNRECOGNIZED_SELECTOR
}

- (void *)mutableItemAtIndex: (size_t)idx
{
	if (idx >= self.count)
		@throw [OFOutOfRangeException exception];

	return (unsigned char *)self.mutableItems + idx * self.itemSize;
}

- (void *)mutableFirstItem
{
	void *mutableItems = self.mutableItems;

	if (mutableItems == NULL || self.count == 0)
		return NULL;

	return mutableItems;
}

- (void *)mutableLastItem
{
	unsigned char *mutableItems = self.mutableItems;
	size_t count = self.count;

	if (mutableItems == NULL || count == 0)
		return NULL;

	return mutableItems + (count - 1) * self.itemSize;
}

- (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;
	return [OFData dataWithItems: (unsigned char *)self.mutableItems +
				      (range.location * itemSize)
			       count: range.length
			    itemSize: itemSize];
}

- (void)addItem: (const void *)item
{


	[self insertItems: item atIndex: self.count count: 1];








}

- (void)insertItem: (const void *)item atIndex: (size_t)idx
{
	[self insertItems: item atIndex: idx count: 1];
}

- (void)addItems: (const void *)items count: (size_t)count
{


	[self insertItems: items atIndex: self.count count: count];







}

- (void)insertItems: (const void *)items
	    atIndex: (size_t)idx
	      count: (size_t)count
{


	OF_UNRECOGNIZED_SELECTOR










}

- (void)increaseCountBy: (size_t)count
{


	OF_UNRECOGNIZED_SELECTOR







}

- (void)removeItemAtIndex: (size_t)idx
{
	[self removeItemsInRange: OFMakeRange(idx, 1)];
}

- (void)removeItemsInRange: (OFRange)range
{



	OF_UNRECOGNIZED_SELECTOR











}

- (void)removeLastItem
{
	size_t count = self.count;


	if (count == 0)
		return;





	[self removeItemsInRange: OFMakeRange(count - 1, 1)];
}

- (void)removeAllItems
{


	[self removeItemsInRange: OFMakeRange(0, self.count)];

}

- (id)copy
{
	return [[OFData alloc] initWithItems: self.mutableItems
				       count: self.count
				    itemSize: self.itemSize];
}

- (void)makeImmutable
{






}




@end

Modified src/OFSecureData.h from [5deb9cb9cd] to [37557f6a68].

28
29
30
31
32
33
34



35
36
37
38
39
40
41
42
43
 *	    deallocated. Check the @ref allowsSwappableMemory property to see
 *	    whether a particular OFSecureData might be allocated in swappable
 *	    memory.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSecureData: OFData
{



	void *_page;
	bool _allowsSwappableMemory;
}

/**
 * @brief Whether the data may be stored in swappable memory.
 */
@property (readonly, nonatomic) bool allowsSwappableMemory;








>
>
>

<







28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
 *	    deallocated. Check the @ref allowsSwappableMemory property to see
 *	    whether a particular OFSecureData might be allocated in swappable
 *	    memory.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSecureData: OFData
{
	unsigned char *_Nullable _items;
	size_t _count, _itemSize;
	bool _freeWhenDone, _allowsSwappableMemory;
	void *_page;

}

/**
 * @brief Whether the data may be stored in swappable memory.
 */
@property (readonly, nonatomic) bool allowsSwappableMemory;

131
132
133
134
135
136
137


138
139
140
141
142
143
144
 * @return An initialized OFSecureData
 */
- (instancetype)initWithCount: (size_t)count
		     itemSize: (size_t)itemSize
	allowsSwappableMemory: (bool)allowsSwappableMemory
    OF_DESIGNATED_INITIALIZER;



- (instancetype)initWithItems: (const void *)items
			count: (size_t)count OF_UNAVAILABLE;
- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize OF_UNAVAILABLE;
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count







>
>







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
 * @return An initialized OFSecureData
 */
- (instancetype)initWithCount: (size_t)count
		     itemSize: (size_t)itemSize
	allowsSwappableMemory: (bool)allowsSwappableMemory
    OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithItemSize: (size_t)itemSize OF_UNAVAILABLE;
- (instancetype)initWithItems: (const void *)items
			count: (size_t)count OF_UNAVAILABLE;
- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize OF_UNAVAILABLE;
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count

Modified src/OFSecureData.m from [47b9727f66] to [a15fe6dfde].

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
	allowsSwappableMemory: (bool)allowsSwappableMemory
{
	return [[[self alloc] initWithCount: count
				   itemSize: itemSize
		      allowsSwappableMemory: allowsSwappableMemory]
	    autorelease];
}

+ (instancetype)dataWithItems: (const void *)items
			count: (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	OF_UNRECOGNIZED_SELECTOR
}

#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path
{
	OF_UNRECOGNIZED_SELECTOR
}
#endif

+ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithStringRepresentation: (OFString *)string
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithBase64EncodedString: (OFString *)string
{
	OF_UNRECOGNIZED_SELECTOR
}


- (instancetype)initWithCount: (size_t)count
	allowsSwappableMemory: (bool)allowsSwappableMemory
{
	return [self initWithCount: count
			  itemSize: 1
	     allowsSwappableMemory: allowsSwappableMemory];







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







335
336
337
338
339
340
341



















































342
343
344
345
346
347
348
	allowsSwappableMemory: (bool)allowsSwappableMemory
{
	return [[[self alloc] initWithCount: count
				   itemSize: itemSize
		      allowsSwappableMemory: allowsSwappableMemory]
	    autorelease];
}




















































- (instancetype)initWithCount: (size_t)count
	allowsSwappableMemory: (bool)allowsSwappableMemory
{
	return [self initWithCount: count
			  itemSize: 1
	     allowsSwappableMemory: allowsSwappableMemory];
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	OF_INVALID_INIT_METHOD
}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{







|




|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







410
411
412
413
414
415
416
417
418
419
420
421
422

















423
424
425
426
427
428
429
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItemSize: (size_t)itemSize

















{
	OF_INVALID_INIT_METHOD
}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
531
532
533
534
535
536
537



538
539















540
541
542
543
544
545
546
				freeMemory(_page, _items, _count * _itemSize);

			removePageIfEmpty(_page);
		}
	}
#endif




	[super dealloc];
}
















- (void *)mutableItems
{
	return _items;
}

- (void *)mutableItemAtIndex: (size_t)idx







>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
				freeMemory(_page, _items, _count * _itemSize);

			removePageIfEmpty(_page);
		}
	}
#endif

	if (_freeWhenDone)
		OFFreeMemory(_items);

	[super dealloc];
}

- (size_t)count
{
	return _count;
}

- (size_t)itemSize
{
	return _itemSize;
}

- (const void *)items
{
	return _items;
}

- (void *)mutableItems
{
	return _items;
}

- (void *)mutableItemAtIndex: (size_t)idx
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

	return copy;
}

- (bool)isEqual: (id)object
{
	OFData *otherData;

	unsigned char diff;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFData class]])
		return false;

	otherData = object;


	if (otherData->_count != _count || otherData->_itemSize != _itemSize)
		return false;

	diff = 0;

	for (size_t i = 0; i < _count * _itemSize; i++)
		diff |= otherData->_items[i] ^ _items[i];

	return (diff == 0);
}

- (OFString *)description
{
	return @"<OFSecureData>";







>









>

|





|







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561

	return copy;
}

- (bool)isEqual: (id)object
{
	OFData *otherData;
	const unsigned char *otherDataItems;
	unsigned char diff;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFData class]])
		return false;

	otherData = object;
	otherDataItems = otherData.items;

	if (otherData.count != _count || otherData.itemSize != _itemSize)
		return false;

	diff = 0;

	for (size_t i = 0; i < _count * _itemSize; i++)
		diff |= otherDataItems[i] ^ _items[i];

	return (diff == 0);
}

- (OFString *)description
{
	return @"<OFSecureData>";