ObjFW  Check-in [80d754522a]

Overview
Comment:Introduce a naming scheme for classes implementing abstract classes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 80d754522ae2da5ef533422a4a3f092065c93ca1eb9465bc033e51b836648dce
User & Date: js on 2011-08-13 10:04:27
Other Links: manifest | tags
Context
2011-08-13
10:16
Introduce a naming scheme for placeholder classes. check-in: bfee66b3ec user: js tags: trunk
10:04
Introduce a naming scheme for classes implementing abstract classes. check-in: 80d754522a user: js tags: trunk
2011-08-12
16:18
Add OFSOCKS5Socket. check-in: 48e58dfed1 user: js tags: trunk
Changes

Modified src/Makefile from [beed6c9c08] to [fcce85d9ef].

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
include ../extra.mk

SUBDIRS = exceptions

LIB = ${OBJFW_SHARED_LIB}
LIB_MAJOR = ${OBJFW_LIB_MAJOR}
LIB_MINOR = ${OBJFW_LIB_MINOR}
STATIC_LIB = ${OBJFW_STATIC_LIB}

SRCS = OFApplication.m			\
       OFArray.m			\

       OFAutoreleasePool.m		\
       OFBlock.m			\
       OFCArray.m			\
       OFConstantString.m		\
       OFCountedSet.m			\
       OFDataArray.m			\
       OFDataArray+Hashing.m		\
       OFDate.m				\
       OFDictionary.m			\
       OFDoubleMatrix.m			\
       OFDoubleVector.m			\
       OFEnumerator.m			\
       OFFile.m				\
       OFFloatMatrix.m			\
       OFFloatVector.m			\
       OFHash.m				\
       OFHTTPRequest.m			\
       OFIntrospection.m		\
       OFList.m				\
       OFMD5Hash.m			\
       OFMutableArray.m			\
       OFMutableCArray.m		\
       OFMutableDictionary.m		\
       OFMutableSet.m			\
       OFMutableString.m		\
       OFNull.m				\
       OFNumber.m			\
       OFObject.m			\
       OFObject+Serialization.m		\











>


<


















|







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
include ../extra.mk

SUBDIRS = exceptions

LIB = ${OBJFW_SHARED_LIB}
LIB_MAJOR = ${OBJFW_LIB_MAJOR}
LIB_MINOR = ${OBJFW_LIB_MINOR}
STATIC_LIB = ${OBJFW_STATIC_LIB}

SRCS = OFApplication.m			\
       OFArray.m			\
       OFArray_adjacent.m		\
       OFAutoreleasePool.m		\
       OFBlock.m			\

       OFConstantString.m		\
       OFCountedSet.m			\
       OFDataArray.m			\
       OFDataArray+Hashing.m		\
       OFDate.m				\
       OFDictionary.m			\
       OFDoubleMatrix.m			\
       OFDoubleVector.m			\
       OFEnumerator.m			\
       OFFile.m				\
       OFFloatMatrix.m			\
       OFFloatVector.m			\
       OFHash.m				\
       OFHTTPRequest.m			\
       OFIntrospection.m		\
       OFList.m				\
       OFMD5Hash.m			\
       OFMutableArray.m			\
       OFMutableArray_adjacent.m	\
       OFMutableDictionary.m		\
       OFMutableSet.m			\
       OFMutableString.m		\
       OFNull.m				\
       OFNumber.m			\
       OFObject.m			\
       OFObject+Serialization.m		\

Modified src/OFArray.m from [da553bca16] to [2988c16d4d].

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
 */

#include "config.h"

#include <stdarg.h>

#import "OFArray.h"
#import "OFCArray.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"

static struct {
	Class isa;
} placeholder;

@implementation OFArrayPlaceholder
- init
{
	return (id)[[OFCArray alloc] init];
}

- initWithObject: (id)object
{
	return (id)[[OFCArray alloc] initWithObject: object];
}

- initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFCArray alloc] initWithObject: firstObject
				     arguments: arguments];
	va_end(arguments);

	return ret;
}

- initWithObject: (id)firstObject
       arguments: (va_list)arguments
{
	return (id)[[OFCArray alloc] initWithObject: firstObject
					  arguments: arguments];
}

- initWithArray: (OFArray*)array
{
	return (id)[[OFCArray alloc] initWithArray: array];
}

- initWithCArray: (id*)objects
{
	return (id)[[OFCArray alloc] initWithCArray: objects];
}

- initWithCArray: (id*)objects
	  length: (size_t)length
{
	return (id)[[OFCArray alloc] initWithCArray: objects
					     length: length];
}

- initWithSerialization: (OFXMLElement*)element
{
	return (id)[[OFCArray alloc] initWithSerialization: element];
}

- retain
{
	return self;
}








|


















|




|








|
|








|
|




|




|





|
|




|







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
 */

#include "config.h"

#include <stdarg.h>

#import "OFArray.h"
#import "OFArray_adjacent.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"

static struct {
	Class isa;
} placeholder;

@implementation OFArrayPlaceholder
- init
{
	return (id)[[OFArray_adjacent alloc] init];
}

- initWithObject: (id)object
{
	return (id)[[OFArray_adjacent alloc] initWithObject: object];
}

- initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFArray_adjacent alloc] initWithObject: firstObject
					     arguments: arguments];
	va_end(arguments);

	return ret;
}

- initWithObject: (id)firstObject
       arguments: (va_list)arguments
{
	return (id)[[OFArray_adjacent alloc] initWithObject: firstObject
						  arguments: arguments];
}

- initWithArray: (OFArray*)array
{
	return (id)[[OFArray_adjacent alloc] initWithArray: array];
}

- initWithCArray: (id*)objects
{
	return (id)[[OFArray_adjacent alloc] initWithCArray: objects];
}

- initWithCArray: (id*)objects
	  length: (size_t)length
{
	return (id)[[OFArray_adjacent alloc] initWithCArray: objects
						     length: length];
}

- initWithSerialization: (OFXMLElement*)element
{
	return (id)[[OFArray_adjacent alloc] initWithSerialization: element];
}

- retain
{
	return self;
}

Added src/OFArray_adjacent.h version [0519520f07].

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFArray.h"

@class OFDataArray;

/**
 * \brief A class for storing objects in an array.
 */
@interface OFArray_adjacent: OFArray
{
	OFDataArray *array;
}
@end

Added src/OFArray_adjacent.m version [f4dc3297f2].









































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdarg.h>

#import "OFArray_adjacent.h"
#import "OFMutableArray_adjacent.h"
#import "OFDataArray.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

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

#import "macros.h"

@implementation OFArray_adjacent
- init
{
	self = [super init];

	@try {
		array = [[OFDataArray alloc] initWithItemSize: sizeof(id)];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithObject: (id)object
{
	self = [self init];

	@try {
		[array addItem: &object];
		[object retain];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithObject: (id)firstObject
       arguments: (va_list)arguments
{
	self = [self init];

	@try {
		id object;

		[array addItem: &firstObject];
		[firstObject retain];

		while ((object = va_arg(arguments, id)) != nil) {
			[array addItem: &object];
			[object retain];
		}
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithArray: (OFArray*)array_
{
	id *cArray;
	size_t i, count;

	self = [self init];

	@try {
		cArray = [array_ cArray];
		count = [array_ count];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		for (i = 0; i < count; i++)
			[cArray[i] retain];

		[array addNItems: count
		      fromCArray: cArray];
	} @catch (id e) {
		for (i = 0; i < count; i++)
			[cArray[i] release];

		/* Prevent double-release of objects */
		[array release];
		array = nil;

		[self release];
		@throw e;
	}

	return self;
}

- initWithCArray: (id*)objects
{
	self = [self init];

	@try {
		id *object;
		size_t count = 0;

		for (object = objects; *object != nil; object++) {
			[*object retain];
			count++;
		}

		[array addNItems: count
		      fromCArray: objects];
	} @catch (id e) {
		id *object;

		for (object = objects; *object != nil; object++)
			[*object release];

		[self release];
		@throw e;
	}

	return self;
}

- initWithCArray: (id*)objects
	  length: (size_t)length
{
	self = [self init];

	@try {
		size_t i;

		for (i = 0; i < length; i++)
			[objects[i] retain];

		[array addNItems: length
		      fromCArray: objects];
	} @catch (id e) {
		size_t i;

		for (i = 0; i < length; i++)
			[objects[i] release];

		[self release];
		@throw e;
	}

	return self;
}

- initWithSerialization: (OFXMLElement*)element
{
	self = [self init];

	@try {
		OFAutoreleasePool *pool, *pool2;
		OFEnumerator *enumerator;
		OFXMLElement *child;

		pool = [[OFAutoreleasePool alloc] init];

		if ((![[element name] isEqual: @"OFArray"] &&
		    ![[element name] isEqual: @"OFMutableArray"]) ||
		    ![[element namespace] isEqual: OF_SERIALIZATION_NS])
			@throw [OFInvalidArgumentException newWithClass: isa
							       selector: _cmd];

		enumerator = [[element children] objectEnumerator];
		pool2 = [[OFAutoreleasePool alloc] init];

		while ((child = [enumerator nextObject]) != nil) {
			id object;

			if (![[child namespace] isEqual: OF_SERIALIZATION_NS])
				continue;

			object = [child objectByDeserializing];
			[array addItem: &object];
			[object retain];

			[pool2 releaseObjects];
		}

		[pool release];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (size_t)count
{
	return [array count];
}

- (id*)cArray
{
	return [array cArray];
}

- (id)objectAtIndex: (size_t)index
{
	return *((id*)[array itemAtIndex: index]);
}

- (void)getObjects: (id*)buffer
	   inRange: (of_range_t)range
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	if (range.start + range.length > count)
		@throw [OFOutOfRangeException newWithClass: isa];

	for (i = 0; i < range.length; i++)
		buffer[i] = cArray[range.start + i];
}

- (size_t)indexOfObject: (id)object
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++)
		if ([cArray[i] isEqual: object])
			return i;

	return OF_INVALID_INDEX;
}

- (size_t)indexOfObjectIdenticalTo: (id)object
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++)
		if (cArray[i] == object)
			return i;

	return OF_INVALID_INDEX;
}


- (OFArray*)objectsInRange: (of_range_t)range
{
	size_t count = [array count];

	if (range.start + range.length > count)
		@throw [OFOutOfRangeException newWithClass: isa];

	return [OFArray arrayWithCArray: (id*)[array cArray] + range.start
				 length: range.length];
}

- (BOOL)isEqual: (id)object
{
	OFArray *otherArray;
	id *cArray, *otherCArray;
	size_t i, count;

	if ([object class] != [OFArray_adjacent class] &&
	    [object class] != [OFMutableArray_adjacent class])
		return [super isEqual: object];

	otherArray = object;

	count = [array count];

	if (count != [otherArray count])
		return NO;

	cArray = [array cArray];
	otherCArray = [otherArray cArray];

	for (i = 0; i < count; i++)
		if (![cArray[i] isEqual: otherCArray[i]])
			return NO;

	return YES;
}

- (uint32_t)hash
{
	id *cArray = [array cArray];
	size_t i, count = [array count];
	uint32_t hash;

	OF_HASH_INIT(hash);

	for (i = 0; i < count; i++) {
		uint32_t h = [cArray[i] hash];

		OF_HASH_ADD(hash, h >> 24);
		OF_HASH_ADD(hash, (h >> 16) & 0xFF);
		OF_HASH_ADD(hash, (h >> 8) & 0xFF);
		OF_HASH_ADD(hash, h & 0xFF);
	}

	OF_HASH_FINALIZE(hash);

	return hash;
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateObjectsUsingBlock: (of_array_enumeration_block_t)block
{
	id *cArray = [array cArray];
	size_t i, count = [array count];
	BOOL stop = NO;

	for (i = 0; i < count && !stop; i++)
		block(cArray[i], i, &stop);
}
#endif

- (void)dealloc
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++)
		[cArray[i] release];

	[array release];

	[super dealloc];
}
@end

Deleted src/OFCArray.h version [a0f3673861].

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
/*
 * Copyright (c) 2008, 2009, 2010, 2011
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFArray.h"

@class OFDataArray;

/**
 * \brief A class for storing objects in an array.
 */
@interface OFCArray: OFArray
{
	OFDataArray *array;
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted src/OFCArray.m version [2c7cd9bb93].

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
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
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdarg.h>

#import "OFCArray.h"
#import "OFMutableCArray.h"
#import "OFDataArray.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

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

#import "macros.h"

@implementation OFCArray
- init
{
	self = [super init];

	@try {
		array = [[OFDataArray alloc] initWithItemSize: sizeof(id)];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithObject: (id)object
{
	self = [self init];

	@try {
		[array addItem: &object];
		[object retain];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithObject: (id)firstObject
       arguments: (va_list)arguments
{
	self = [self init];

	@try {
		id object;

		[array addItem: &firstObject];
		[firstObject retain];

		while ((object = va_arg(arguments, id)) != nil) {
			[array addItem: &object];
			[object retain];
		}
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithArray: (OFArray*)array_
{
	id *cArray;
	size_t i, count;

	self = [self init];

	@try {
		cArray = [array_ cArray];
		count = [array_ count];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		for (i = 0; i < count; i++)
			[cArray[i] retain];

		[array addNItems: count
		      fromCArray: cArray];
	} @catch (id e) {
		for (i = 0; i < count; i++)
			[cArray[i] release];

		/* Prevent double-release of objects */
		[array release];
		array = nil;

		[self release];
		@throw e;
	}

	return self;
}

- initWithCArray: (id*)objects
{
	self = [self init];

	@try {
		id *object;
		size_t count = 0;

		for (object = objects; *object != nil; object++) {
			[*object retain];
			count++;
		}

		[array addNItems: count
		      fromCArray: objects];
	} @catch (id e) {
		id *object;

		for (object = objects; *object != nil; object++)
			[*object release];

		[self release];
		@throw e;
	}

	return self;
}

- initWithCArray: (id*)objects
	  length: (size_t)length
{
	self = [self init];

	@try {
		size_t i;

		for (i = 0; i < length; i++)
			[objects[i] retain];

		[array addNItems: length
		      fromCArray: objects];
	} @catch (id e) {
		size_t i;

		for (i = 0; i < length; i++)
			[objects[i] release];

		[self release];
		@throw e;
	}

	return self;
}

- initWithSerialization: (OFXMLElement*)element
{
	self = [self init];

	@try {
		OFAutoreleasePool *pool, *pool2;
		OFEnumerator *enumerator;
		OFXMLElement *child;

		pool = [[OFAutoreleasePool alloc] init];

		if ((![[element name] isEqual: @"OFArray"] &&
		    ![[element name] isEqual: @"OFMutableArray"]) ||
		    ![[element namespace] isEqual: OF_SERIALIZATION_NS])
			@throw [OFInvalidArgumentException newWithClass: isa
							       selector: _cmd];

		enumerator = [[element children] objectEnumerator];
		pool2 = [[OFAutoreleasePool alloc] init];

		while ((child = [enumerator nextObject]) != nil) {
			id object;

			if (![[child namespace] isEqual: OF_SERIALIZATION_NS])
				continue;

			object = [child objectByDeserializing];
			[array addItem: &object];
			[object retain];

			[pool2 releaseObjects];
		}

		[pool release];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (size_t)count
{
	return [array count];
}

- (id*)cArray
{
	return [array cArray];
}

- (id)objectAtIndex: (size_t)index
{
	return *((id*)[array itemAtIndex: index]);
}

- (void)getObjects: (id*)buffer
	   inRange: (of_range_t)range
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	if (range.start + range.length > count)
		@throw [OFOutOfRangeException newWithClass: isa];

	for (i = 0; i < range.length; i++)
		buffer[i] = cArray[range.start + i];
}

- (size_t)indexOfObject: (id)object
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++)
		if ([cArray[i] isEqual: object])
			return i;

	return OF_INVALID_INDEX;
}

- (size_t)indexOfObjectIdenticalTo: (id)object
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++)
		if (cArray[i] == object)
			return i;

	return OF_INVALID_INDEX;
}


- (OFArray*)objectsInRange: (of_range_t)range
{
	size_t count = [array count];

	if (range.start + range.length > count)
		@throw [OFOutOfRangeException newWithClass: isa];

	return [OFArray arrayWithCArray: (id*)[array cArray] + range.start
				 length: range.length];
}

- (BOOL)isEqual: (id)object
{
	OFArray *otherArray;
	id *cArray, *otherCArray;
	size_t i, count;

	if (![object isKindOfClass: [OFCArray class]] &&
	    ![object isKindOfClass: [OFMutableCArray class]])
		return [super isEqual: object];

	otherArray = object;

	count = [array count];

	if (count != [otherArray count])
		return NO;

	cArray = [array cArray];
	otherCArray = [otherArray cArray];

	for (i = 0; i < count; i++)
		if (![cArray[i] isEqual: otherCArray[i]])
			return NO;

	return YES;
}

- (uint32_t)hash
{
	id *cArray = [array cArray];
	size_t i, count = [array count];
	uint32_t hash;

	OF_HASH_INIT(hash);

	for (i = 0; i < count; i++) {
		uint32_t h = [cArray[i] hash];

		OF_HASH_ADD(hash, h >> 24);
		OF_HASH_ADD(hash, (h >> 16) & 0xFF);
		OF_HASH_ADD(hash, (h >> 8) & 0xFF);
		OF_HASH_ADD(hash, h & 0xFF);
	}

	OF_HASH_FINALIZE(hash);

	return hash;
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateObjectsUsingBlock: (of_array_enumeration_block_t)block
{
	id *cArray = [array cArray];
	size_t i, count = [array count];
	BOOL stop = NO;

	for (i = 0; i < count && !stop; i++)
		block(cArray[i], i, &stop);
}
#endif

- (void)dealloc
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++)
		[cArray[i] release];

	[array release];

	[super dealloc];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































































































































































































































































































































































































































































































































































































































































Modified src/OFMutableArray.m from [8df097f31b] to [d57bcb65c8].

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
 */

#include "config.h"

#include <string.h>

#import "OFMutableArray.h"
#import "OFMutableCArray.h"
#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"

static struct {
	Class isa;
} placeholder;

@implementation OFMutableArrayPlaceholder
- init
{
	return (id)[[OFMutableCArray alloc] init];
}

- initWithObject: (id)object
{
	return (id)[[OFMutableCArray alloc] initWithObject: object];
}

- initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFMutableCArray alloc] initWithObject: firstObject
					    arguments: arguments];
	va_end(arguments);

	return ret;
}

- initWithObject: (id)firstObject
       arguments: (va_list)arguments
{
	return (id)[[OFMutableCArray alloc] initWithObject: firstObject
						 arguments: arguments];
}

- initWithArray: (OFArray*)array
{
	return (id)[[OFMutableCArray alloc] initWithArray: array];
}

- initWithCArray: (id*)objects
{
	return (id)[[OFMutableCArray alloc] initWithCArray: objects];
}

- initWithCArray: (id*)objects
	  length: (size_t)length
{
	return (id)[[OFMutableCArray alloc] initWithCArray: objects
						    length: length];
}

- initWithSerialization: (OFXMLElement*)element
{

	return (id)[[OFMutableCArray alloc] initWithSerialization: element];
}

- retain
{
	return self;
}








|
















|




|








|
|








|
|




|




|





|
|




>
|







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
 */

#include "config.h"

#include <string.h>

#import "OFMutableArray.h"
#import "OFMutableArray_adjacent.h"
#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"

static struct {
	Class isa;
} placeholder;

@implementation OFMutableArrayPlaceholder
- init
{
	return (id)[[OFMutableArray_adjacent alloc] init];
}

- initWithObject: (id)object
{
	return (id)[[OFMutableArray_adjacent alloc] initWithObject: object];
}

- initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFMutableArray_adjacent alloc] initWithObject: firstObject
						    arguments: arguments];
	va_end(arguments);

	return ret;
}

- initWithObject: (id)firstObject
       arguments: (va_list)arguments
{
	return (id)[[OFMutableArray_adjacent alloc] initWithObject: firstObject
							 arguments: arguments];
}

- initWithArray: (OFArray*)array
{
	return (id)[[OFMutableArray_adjacent alloc] initWithArray: array];
}

- initWithCArray: (id*)objects
{
	return (id)[[OFMutableArray_adjacent alloc] initWithCArray: objects];
}

- initWithCArray: (id*)objects
	  length: (size_t)length
{
	return (id)[[OFMutableArray_adjacent alloc] initWithCArray: objects
							    length: length];
}

- initWithSerialization: (OFXMLElement*)element
{
	return (id)[[OFMutableArray_adjacent alloc]
	    initWithSerialization: element];
}

- retain
{
	return self;
}

Added src/OFMutableArray_adjacent.h version [b465e001bc].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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, 2009, 2010, 2011
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFArray.h"

@class OFDataArray;

/**
 * \brief A class for storing, adding and removing objects in an array.
 */
@interface OFMutableArray_adjacent: OFMutableArray
{
	OFDataArray   *array;
	unsigned long mutations;
}
@end

Added src/OFMutableArray_adjacent.m version [dac9f5ca9a].















































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <string.h>

#import "OFMutableArray_adjacent.h"
#import "OFArray_adjacent.h"
#import "OFDataArray.h"
#import "OFAutoreleasePool.h"

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

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

- (void)addObject: (id)object
{
	[array addItem: &object];
	[object retain];

	mutations++;
}

- (void)addObject: (id)object
	  atIndex: (size_t)index
{
	[array addItem: &object
	       atIndex: index];
	[object retain];

	mutations++;
}

- (void)replaceObject: (id)oldObject
	   withObject: (id)newObject
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++) {
		if ([cArray[i] isEqual: oldObject]) {
			[newObject retain];
			[cArray[i] release];
			cArray[i] = newObject;

			return;
		}
	}
}

- (void)replaceObjectAtIndex: (size_t)index
		  withObject: (id)object
{
	id *cArray = [array cArray];
	id oldObject;

	if (index >= [array count])
		@throw [OFOutOfRangeException newWithClass: isa];

	oldObject = cArray[index];
	cArray[index] = [object retain];
	[oldObject release];
}

- (void)replaceObjectIdenticalTo: (id)oldObject
		      withObject: (id)newObject
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++) {
		if (cArray[i] == oldObject) {
			[newObject retain];
			[cArray[i] release];
			cArray[i] = newObject;

			return;
		}
	}
}

- (void)removeObject: (id)object
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++) {
		if ([cArray[i] isEqual: object]) {
			object = cArray[i];

			[array removeItemAtIndex: i];
			mutations++;

			[object release];

			return;
		}
	}
}

- (void)removeObjectIdenticalTo: (id)object
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++) {
		if (cArray[i] == object) {
			[array removeItemAtIndex: i];
			mutations++;

			[object release];

			return;
		}
	}
}

- (void)removeObjectAtIndex: (size_t)index
{
	id object = [self objectAtIndex: index];
	[array removeItemAtIndex: index];
	[object release];

	mutations++;
}

- (void)removeNObjects: (size_t)nObjects
{
	id *cArray = [array cArray], *copy;
	size_t i, count = [array count];

	if (nObjects > count)
		@throw [OFOutOfRangeException newWithClass: isa];

	copy = [self allocMemoryForNItems: nObjects
				 withSize: sizeof(id)];
	memcpy(copy, cArray + (count - nObjects), nObjects * sizeof(id));

	@try {
		[array removeNItems: nObjects];
		mutations++;

		for (i = 0; i < nObjects; i++)
			[copy[i] release];
	} @finally {
		[self freeMemory: copy];
	}
}

- (void)removeObjectsInRange: (of_range_t)range
{
	id *cArray = [array cArray], *copy;
	size_t i, count = [array count];

	if (range.length > count - range.start)
		@throw [OFOutOfRangeException newWithClass: isa];

	copy = [self allocMemoryForNItems: range.length
				 withSize: sizeof(id)];
	memcpy(copy, cArray + range.start, range.length * sizeof(id));

	@try {
		[array removeNItems: range.length
			    atIndex: range.start];
		mutations++;

		for (i = 0; i < range.length; i++)
			[copy[i] release];
	} @finally {
		[self freeMemory: copy];
	}
}

- (void)removeLastObject
{
	id object = [self objectAtIndex: [array count] - 1];
	[array removeLastItem];
	[object release];

	mutations++;
}

- (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state
			   objects: (id*)objects
			     count: (int)count
{
	/*
	 * Super means the implementation from OFArray here, as OFMutableArray
	 * does not reimplement it. As OFArray_adjacent does not reimplement it
	 * either, this is fine.
	 */
	int ret = [super countByEnumeratingWithState: state
					     objects: objects
					       count: count];

	state->mutationsPtr = &mutations;

	return ret;
}

- (OFEnumerator*)objectEnumerator
{
	return [[[OFArrayEnumerator alloc]
	    initWithArray: self
	     mutationsPtr: &mutations] autorelease];
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateObjectsUsingBlock: (of_array_enumeration_block_t)block
{
	id *cArray = [array cArray];
	size_t i, count = [array count];
	BOOL stop = NO;
	unsigned long mutations2 = mutations;

	for (i = 0; i < count && !stop; i++) {
		if (mutations != mutations2)
			@throw [OFEnumerationMutationException
			    newWithClass: isa
				  object: self];

		block(cArray[i], i, &stop);
	}
}

- (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block
{
	id *cArray = [array cArray];
	size_t i, count = [array count];
	BOOL stop = NO;
	unsigned long mutations2 = mutations;

	for (i = 0; i < count && !stop; i++) {
		id newObject;

		if (mutations != mutations2)
			@throw [OFEnumerationMutationException
			    newWithClass: isa
				  object: self];

		newObject = block(cArray[i], i, &stop);

		if (newObject == nil)
			@throw [OFInvalidArgumentException newWithClass: isa
							       selector: _cmd];

		[newObject retain];
		[cArray[i] release];
		cArray[i] = newObject;
	}
}
#endif

- (void)makeImmutable
{
	isa = [OFArray_adjacent class];
}
@end

Deleted src/OFMutableCArray.h version [cc4737ccfc].

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, 2009, 2010, 2011
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFArray.h"

@class OFDataArray;

/**
 * \brief A class for storing, adding and removing objects in an array.
 */
@interface OFMutableCArray: OFMutableArray
{
	OFDataArray   *array;
	unsigned long mutations;
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































Deleted src/OFMutableCArray.m version [5511bcf0c5].

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
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <string.h>

#import "OFMutableCArray.h"
#import "OFCArray.h"
#import "OFDataArray.h"
#import "OFAutoreleasePool.h"

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

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

- (void)addObject: (id)object
{
	[array addItem: &object];
	[object retain];

	mutations++;
}

- (void)addObject: (id)object
	  atIndex: (size_t)index
{
	[array addItem: &object
	       atIndex: index];
	[object retain];

	mutations++;
}

- (void)replaceObject: (id)oldObject
	   withObject: (id)newObject
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++) {
		if ([cArray[i] isEqual: oldObject]) {
			[newObject retain];
			[cArray[i] release];
			cArray[i] = newObject;

			return;
		}
	}
}

- (void)replaceObjectAtIndex: (size_t)index
		  withObject: (id)object
{
	id *cArray = [array cArray];
	id oldObject;

	if (index >= [array count])
		@throw [OFOutOfRangeException newWithClass: isa];

	oldObject = cArray[index];
	cArray[index] = [object retain];
	[oldObject release];
}

- (void)replaceObjectIdenticalTo: (id)oldObject
		      withObject: (id)newObject
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++) {
		if (cArray[i] == oldObject) {
			[newObject retain];
			[cArray[i] release];
			cArray[i] = newObject;

			return;
		}
	}
}

- (void)removeObject: (id)object
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++) {
		if ([cArray[i] isEqual: object]) {
			object = cArray[i];

			[array removeItemAtIndex: i];
			mutations++;

			[object release];

			return;
		}
	}
}

- (void)removeObjectIdenticalTo: (id)object
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

	for (i = 0; i < count; i++) {
		if (cArray[i] == object) {
			[array removeItemAtIndex: i];
			mutations++;

			[object release];

			return;
		}
	}
}

- (void)removeObjectAtIndex: (size_t)index
{
	id object = [self objectAtIndex: index];
	[array removeItemAtIndex: index];
	[object release];

	mutations++;
}

- (void)removeNObjects: (size_t)nObjects
{
	id *cArray = [array cArray], *copy;
	size_t i, count = [array count];

	if (nObjects > count)
		@throw [OFOutOfRangeException newWithClass: isa];

	copy = [self allocMemoryForNItems: nObjects
				 withSize: sizeof(id)];
	memcpy(copy, cArray + (count - nObjects), nObjects * sizeof(id));

	@try {
		[array removeNItems: nObjects];
		mutations++;

		for (i = 0; i < nObjects; i++)
			[copy[i] release];
	} @finally {
		[self freeMemory: copy];
	}
}

- (void)removeObjectsInRange: (of_range_t)range
{
	id *cArray = [array cArray], *copy;
	size_t i, count = [array count];

	if (range.length > count - range.start)
		@throw [OFOutOfRangeException newWithClass: isa];

	copy = [self allocMemoryForNItems: range.length
				 withSize: sizeof(id)];
	memcpy(copy, cArray + range.start, range.length * sizeof(id));

	@try {
		[array removeNItems: range.length
			    atIndex: range.start];
		mutations++;

		for (i = 0; i < range.length; i++)
			[copy[i] release];
	} @finally {
		[self freeMemory: copy];
	}
}

- (void)removeLastObject
{
	id object = [self objectAtIndex: [array count] - 1];
	[array removeLastItem];
	[object release];

	mutations++;
}

- (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state
			   objects: (id*)objects
			     count: (int)count
{
	/*
	 * Super means the implementation from OFArray here, as OFMutableArray
	 * does not reimplement it. As OFCArray does not reimplement it either,
	 * this is fine.
	 */
	int ret = [super countByEnumeratingWithState: state
					     objects: objects
					       count: count];

	state->mutationsPtr = &mutations;

	return ret;
}

- (OFEnumerator*)objectEnumerator
{
	return [[[OFArrayEnumerator alloc]
	    initWithArray: self
	     mutationsPtr: &mutations] autorelease];
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateObjectsUsingBlock: (of_array_enumeration_block_t)block
{
	id *cArray = [array cArray];
	size_t i, count = [array count];
	BOOL stop = NO;
	unsigned long mutations2 = mutations;

	for (i = 0; i < count && !stop; i++) {
		if (mutations != mutations2)
			@throw [OFEnumerationMutationException
			    newWithClass: isa
				  object: self];

		block(cArray[i], i, &stop);
	}
}

- (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block
{
	id *cArray = [array cArray];
	size_t i, count = [array count];
	BOOL stop = NO;
	unsigned long mutations2 = mutations;

	for (i = 0; i < count && !stop; i++) {
		id newObject;

		if (mutations != mutations2)
			@throw [OFEnumerationMutationException
			    newWithClass: isa
				  object: self];

		newObject = block(cArray[i], i, &stop);

		if (newObject == nil)
			@throw [OFInvalidArgumentException newWithClass: isa
							       selector: _cmd];

		[newObject retain];
		[cArray[i] release];
		cArray[i] = newObject;
	}
}
#endif

- (void)makeImmutable
{
	isa = [OFCArray class];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<