ObjFW  Diff

Differences From Artifact [ba1c079bde]:

To Artifact [0029147821]:


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

-
+


















-
-

-
+









-
+


-
-
-
-
-
-
-
-
-
-

-
-
+
+


















-
+



-
+







-
+





-
+
+





-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-

-
-


-
+




-
+




-
+








-
+








-
+





-
+




-
+


-
+
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-






+
-
+

















-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+






+
+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2024 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 <stdlib.h>
#include <string.h>

#include <assert.h>

#import "OFMutableArray.h"
#import "OFMutableAdjacentArray.h"
#import "OFConcreteMutableArray.h"

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

static struct {
	Class isa;
} placeholder;

@interface OFMutableArrayPlaceholder: OFMutableArray
@interface OFPlaceholderMutableArray: OFMutableArray
@end

static OFComparisonResult
compare(id left, id right, SEL selector)
{
	OFComparisonResult (*comparator)(id, SEL, id) =
	    (OFComparisonResult (*)(id, SEL, id))
	    [left methodForSelector: selector];

	return comparator(left, selector, right);
}

static void
quicksort(OFMutableArray *array, size_t left, size_t right, SEL selector,
    OFArraySortOptions options)
quicksort(OFMutableArray *array, size_t left, size_t right,
    OFCompareFunction compare, void *context, OFArraySortOptions options)
{
	OFComparisonResult ascending, descending;

	if (options & OFArraySortDescending) {
		ascending = OFOrderedDescending;
		descending = OFOrderedAscending;
	} else {
		ascending = OFOrderedAscending;
		descending = OFOrderedDescending;
	}

	while (left < right) {
		size_t i = left;
		size_t j = right - 1;
		id pivot = [array objectAtIndex: right];

		do {
			while (compare([array objectAtIndex: i], pivot,
			    selector) != descending && i < right)
			    context) != descending && i < right)
				i++;

			while (compare([array objectAtIndex: j], pivot,
			    selector) != ascending && j > left)
			    context) != ascending && j > left)
				j--;

			if (i < j)
				[array exchangeObjectAtIndex: i
					   withObjectAtIndex: j];
		} while (i < j);

		if (compare([array objectAtIndex: i], pivot, selector) ==
		if (compare([array objectAtIndex: i], pivot, context) ==
		    descending)
			[array exchangeObjectAtIndex: i
				   withObjectAtIndex: right];

		if (i > 0)
			quicksort(array, left, i - 1, selector, options);
			quicksort(array, left, i - 1, compare, context,
			    options);

		left = i + 1;
	}
}

#ifdef OF_HAVE_BLOCKS
static void
quicksortWithBlock(OFMutableArray *array, size_t left, size_t right,
    OFComparator comparator, OFArraySortOptions options)
{
	OFComparisonResult ascending, descending;

@implementation OFPlaceholderMutableArray
	if (options & OFArraySortDescending) {
		ascending = OFOrderedDescending;
		descending = OFOrderedAscending;
	} else {
		ascending = OFOrderedAscending;
		descending = OFOrderedDescending;
	}

#ifdef __clang__
	while (left < right) {
		size_t i = left;
		size_t j = right - 1;
		id pivot = [array objectAtIndex: right];

/* We intentionally don't call into super, so silence the warning. */
		do {
			while (comparator([array objectAtIndex: i], pivot) !=
			    descending && i < right)
				i++;

# pragma clang diagnostic push
			while (comparator([array objectAtIndex: j], pivot) !=
			    ascending && j > left)
				j--;

# pragma clang diagnostic ignored "-Wunknown-pragmas"
			if (i < j)
				[array exchangeObjectAtIndex: i
					   withObjectAtIndex: j];
		} while (i < j);

# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
		if (comparator([array objectAtIndex: i], pivot) == descending)
			[array exchangeObjectAtIndex: i
				   withObjectAtIndex: right];

		if (i > 0)
			quicksortWithBlock(array, left, i - 1, comparator,
			    options);

		left = i + 1;
	}
}
#endif

@implementation OFMutableArrayPlaceholder
- (instancetype)init
{
	return (id)[[OFMutableAdjacentArray alloc] init];
	return (id)[[OFConcreteMutableArray alloc] init];
}

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

- (instancetype)initWithObject: (id)object
{
	return (id)[[OFMutableAdjacentArray alloc] initWithObject: object];
	return (id)[[OFConcreteMutableArray alloc] initWithObject: object];
}

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

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

	return ret;
}

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

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

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	return (id)[[OFMutableAdjacentArray alloc] initWithObjects: objects
	return (id)[[OFConcreteMutableArray alloc] initWithObjects: objects
							     count: count];
}

#ifdef __clang__
- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableAdjacentArray alloc]
	    initWithSerialization: element];
}

# pragma clang diagnostic pop
- (instancetype)retain
{
	return self;
}

#endif
- (instancetype)autorelease
{

	return self;
}

OF_SINGLETON_METHODS
- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFMutableArray
+ (void)initialize
{
	if (self == [OFMutableArray class])
		object_setClass((id)&placeholder,
		placeholder.isa = [OFMutableArrayPlaceholder class];
		    [OFPlaceholderMutableArray class]);
}

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

	return [super alloc];
}

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

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

}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithObjects: (id const *)objects
			  count: (size_t)count
{
	return [super init];
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (id)copy
{
	return [[OFArray alloc] initWithArray: self];
}

- (void)addObject: (id)object
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
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







+
+
+
+
+
+
+
+
+
+
+









-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+








-
+







	}
}

- (void)sort
{
	[self sortUsingSelector: @selector(compare:) options: 0];
}

static OFComparisonResult
selectorCompare(id left, id right, void *context)
{
	SEL selector = context;
	OFComparisonResult (*comparator)(id, SEL, id) =
	    (OFComparisonResult (*)(id, SEL, id))
	    [left methodForSelector: selector];

	return comparator(left, selector, right);
}

- (void)sortUsingSelector: (SEL)selector
		  options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksort(self, 0, count - 1, selector, options);
	quicksort(self, 0, count - 1, selectorCompare, (void *)selector,
	    options);
}

- (void)sortUsingFunction: (OFCompareFunction)compare
		  context: (void *)context
		  options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksort(self, 0, count - 1, compare, context, options);
}

#ifdef OF_HAVE_BLOCKS
static OFComparisonResult
blockCompare(id left, id right, void *context)
{
	OFComparator block = (OFComparator)context;

	return block(left, right);
}

- (void)sortUsingComparator: (OFComparator)comparator
		    options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksortWithBlock(self, 0, count - 1, comparator, options);
	quicksort(self, 0, count - 1, blockCompare, comparator, options);
}
#endif

- (void)reverse
{
	size_t i, j, count = self.count;