ObjFW  Check-in [daa11c19cb]

Overview
Comment:Add -[OFMutableArray sortUsingSelector:options:]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: daa11c19cbd4331d9e797f6409d223a92e087f7742b1d9b91099a2fe2546f40d
User & Date: js on 2017-08-12 21:03:02
Other Links: manifest | tags
Context
2017-08-13
11:51
Add -[OFMutableData increaseCountBy:] check-in: e3c4bf8e3b user: js tags: trunk
2017-08-12
21:03
Add -[OFMutableArray sortUsingSelector:options:] check-in: daa11c19cb user: js tags: trunk
14:23
-[OFStream write{Data,String}:]: Check for nil check-in: 73b242894c user: js tags: trunk
Changes

Modified src/OFArray.h from [768648064e] to [39352fb17f].

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
 * @param object The object to perform the selector with on all objects in the
 *	      array
 */
- (void)makeObjectsPerformSelector: (SEL)selector
			withObject: (nullable id)object;

/*!
 * @brief Returns a sorted copy of the array.
 *
 * @return A sorted copy of the array
 */
- (OFArray OF_GENERIC(ObjectType) *)sortedArray;

/*!










 * @brief Returns a sorted copy of the array.



 *






 * @param options The options to use when sorting the array.@n
 *		  Possible values are:
 *		  Value                      | Description
 *		  ---------------------------|-------------------------
 *		  `OF_ARRAY_SORT_DESCENDING` | Sort in descending order
 * @return A sorted copy of the array
 */
- (OFArray OF_GENERIC(ObjectType) *)sortedArrayWithOptions: (int)options;




/*!
 * @brief Returns a copy of the array with the order reversed.
 *
 * @return A copy of the array with the order reversed
 */
- (OFArray OF_GENERIC(ObjectType) *)reversedArray;







|






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







|
>
>
>







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
 * @param object The object to perform the selector with on all objects in the
 *	      array
 */
- (void)makeObjectsPerformSelector: (SEL)selector
			withObject: (nullable id)object;

/*!
 * @brief Returns a copy of the array sorted in ascending order.
 *
 * @return A sorted copy of the array
 */
- (OFArray OF_GENERIC(ObjectType) *)sortedArray;

/*!
 * @brief Returns a copy of the array sorted using the specified selector and
 *	  options.
 *
 * @param selector The selector to use to sort the array. It's signature
 *		   should be the same as that of @ref compare:.
 * @param options The options to use when sorting the array.@n
 *		  Possible values are:
 *		  Value                      | Description
 *		  ---------------------------|-------------------------
 *		  `OF_ARRAY_SORT_DESCENDING` | Sort in descending order
 * @return A sorted copy of the array
 */
- (OFArray OF_GENERIC(ObjectType) *)sortedArrayUsingSelector: (SEL)selector
						     options: (int)options;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Returns a copy of the array sorted using the specified selector and
 *	  options.
 *
 * @param comparator The comparator to use to sort the array
 * @param options The options to use when sorting the array.@n
 *		  Possible values are:
 *		  Value                      | Description
 *		  ---------------------------|-------------------------
 *		  `OF_ARRAY_SORT_DESCENDING` | Sort in descending order
 * @return A sorted copy of the array
 */
- (OFArray OF_GENERIC(ObjectType) *)
    sortedArrayUsingComparator: (of_comparator_t)comparator
		       options: (int)options;
#endif

/*!
 * @brief Returns a copy of the array with the order reversed.
 *
 * @return A copy of the array with the order reversed
 */
- (OFArray OF_GENERIC(ObjectType) *)reversedArray;

Modified src/OFArray.m from [15022d3186] to [b6dec58036].

731
732
733
734
735
736
737

738














739
740
741

742
743
744
745
746
747

748
749
750
751
752
753
754
	[new sort];

	[new makeImmutable];

	return new;
}


- (OFArray *)sortedArrayWithOptions: (int)options














{
	OFMutableArray *new = [[self mutableCopy] autorelease];


	[new sortWithOptions: options];

	[new makeImmutable];

	return new;
}


- (OFArray *)reversedArray
{
	OFMutableArray *new = [[self mutableCopy] autorelease];

	[new reverse];








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



>
|





>







731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
	[new sort];

	[new makeImmutable];

	return new;
}

- (OFArray *)sortedArrayUsingSelector: (SEL)selector
			      options: (int)options
{
	OFMutableArray *new = [[self mutableCopy] autorelease];

	[new sortUsingSelector: selector
		       options: options];

	[new makeImmutable];

	return new;
}

#ifdef OF_HAVE_BLOCKS
- (OFArray *)sortedArrayUsingComparator: (of_comparator_t)comparator
				options: (int)options
{
	OFMutableArray *new = [[self mutableCopy] autorelease];

	[new sortUsingComparator: comparator
			 options: options];

	[new makeImmutable];

	return new;
}
#endif

- (OFArray *)reversedArray
{
	OFMutableArray *new = [[self mutableCopy] autorelease];

	[new reverse];

Modified src/OFMutableArray.h from [8b2d3f8705] to [8b66863b27].

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
 * @param index1 The index of the first object to exchange
 * @param index2 The index of the second object to exchange
 */
- (void)exchangeObjectAtIndex: (size_t)index1
	    withObjectAtIndex: (size_t)index2;

/*!
 * @brief Sorts the array.
 */
- (void)sort;

/*!
 * @brief Sorts the array.
 *
















 * @param options The options to use when sorting the array.@n
 *		  Possible values are:
 *		  Value                      | Description
 *		  ---------------------------|-------------------------
 *		  `OF_ARRAY_SORT_DESCENDING` | Sort in descending order
 */

- (void)sortWithOptions: (int)options;


/*!
 * @brief Reverts the order of the objects in the array.
 */
- (void)reverse;

/*!







|




|

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






>
|
>







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
 * @param index1 The index of the first object to exchange
 * @param index2 The index of the second object to exchange
 */
- (void)exchangeObjectAtIndex: (size_t)index1
	    withObjectAtIndex: (size_t)index2;

/*!
 * @brief Sorts the array in ascending order.
 */
- (void)sort;

/*!
 * @brief Sorts the array using the specified selector and options.
 *
 * @param selector The selector to use to sort the array. It's signature
 *		   should be the same as that of @ref compare:.
 * @param options The options to use when sorting the array.@n
 *		  Possible values are:
 *		  Value                      | Description
 *		  ---------------------------|-------------------------
 *		  `OF_ARRAY_SORT_DESCENDING` | Sort in descending order
 */
- (void)sortUsingSelector: (SEL)selector
		  options: (int)options;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Sorts the array using the specified comparator and options.
 *
 * @param comparator The comparator to use to sort the array
 * @param options The options to use when sorting the array.@n
 *		  Possible values are:
 *		  Value                      | Description
 *		  ---------------------------|-------------------------
 *		  `OF_ARRAY_SORT_DESCENDING` | Sort in descending order
 */
- (void)sortUsingComparator: (of_comparator_t)comparator
		    options: (int)options;
#endif

/*!
 * @brief Reverts the order of the objects in the array.
 */
- (void)reverse;

/*!

Modified src/OFMutableArray.m from [f7473af41f] to [706da4f76f].

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
static struct {
	Class isa;
} placeholder;

@interface OFMutableArray_placeholder: OFMutableArray
@end











static void
quicksort(OFMutableArray *array, size_t left, size_t right, int options)















































{
	of_comparison_result_t ascending, descending;

	if (options & OF_ARRAY_SORT_DESCENDING) {
		ascending = OF_ORDERED_DESCENDING;
		descending = OF_ORDERED_ASCENDING;
	} else {
		ascending = OF_ORDERED_ASCENDING;
		descending = OF_ORDERED_DESCENDING;
	}

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

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

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

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

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

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


		left = i + 1;
	}
}


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








>
>
>
>
>
>
>
>
>
>

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

















|



|








|




|
>




>







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
static struct {
	Class isa;
} placeholder;

@interface OFMutableArray_placeholder: OFMutableArray
@end

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

	return comparator(left, selector, right);
}

static void
quicksort(OFMutableArray *array, size_t left, size_t right, SEL selector,
    int options)
{
	of_comparison_result_t ascending, descending;

	if (options & OF_ARRAY_SORT_DESCENDING) {
		ascending = OF_ORDERED_DESCENDING;
		descending = OF_ORDERED_ASCENDING;
	} else {
		ascending = OF_ORDERED_ASCENDING;
		descending = OF_ORDERED_DESCENDING;
	}

	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)
				i++;

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

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

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

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

		left = i + 1;
	}
}

#ifdef OF_HAVE_BLOCKS
static void
quicksortWithBlock(OFMutableArray *array, size_t left, size_t right,
    of_comparator_t comparator, int options)
{
	of_comparison_result_t ascending, descending;

	if (options & OF_ARRAY_SORT_DESCENDING) {
		ascending = OF_ORDERED_DESCENDING;
		descending = OF_ORDERED_ASCENDING;
	} else {
		ascending = OF_ORDERED_ASCENDING;
		descending = OF_ORDERED_DESCENDING;
	}

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

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

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

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

		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 OFMutableArray_placeholder
- init
{
	return (id)[[OFMutableArray_adjacent alloc] init];
}

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
	} @finally {
		[object1 release];
	}
}

- (void)sort
{

	[self sortWithOptions: 0];
}


- (void)sortWithOptions: (int)options












{
	size_t count = [self count];

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

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


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

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







>
|


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






|

>







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
	} @finally {
		[object1 release];
	}
}

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

- (void)sortUsingSelector: (SEL)selector
		  options: (int)options
{
	size_t count = [self count];

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

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

#ifdef OF_HAVE_BLOCKS
- (void)sortUsingComparator: (of_comparator_t)comparator
		    options: (int)options
{
	size_t count = [self count];

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

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

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

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

Modified src/OFObject.h from [9973173cd1] to [eac4bbd7b8].

43
44
45
46
47
48
49












50
51
52
53
54
55
56
	/*! The left object is smaller than the right */
	OF_ORDERED_ASCENDING = -1,
	/*! Both objects are equal */
	OF_ORDERED_SAME = 0,
	/*! The left object is bigger than the right */
	OF_ORDERED_DESCENDING = 1
} of_comparison_result_t;













/*!
 * @brief An enum for storing endianess.
 */
typedef enum {
	/*! Most significant byte first (big endian) */
	OF_BYTE_ORDER_BIG_ENDIAN,







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







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
	/*! The left object is smaller than the right */
	OF_ORDERED_ASCENDING = -1,
	/*! Both objects are equal */
	OF_ORDERED_SAME = 0,
	/*! The left object is bigger than the right */
	OF_ORDERED_DESCENDING = 1
} of_comparison_result_t;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief A comparator to compare two objects.
 *
 * @param left The left object
 * @param right The right object
 * @return The order of the objects
 */
typedef of_comparison_result_t (^of_comparator_t)(id _Nonnull left,
    id _Nonnull right);
#endif

/*!
 * @brief An enum for storing endianess.
 */
typedef enum {
	/*! Most significant byte first (big endian) */
	OF_BYTE_ORDER_BIG_ENDIAN,

Modified tests/OFArrayTests.m from [b0ab3f0686] to [4017a0a9f1].

255
256
257
258
259
260
261

262
263
264
265
266
267
268
269

	m[1] = [[a[0] mutableCopy] autorelease];
	[m[1] addObject: @"0"];
	[m[1] addObject: @"z"];
	TEST(@"-[sortedArray]",
	    [[m[1] sortedArray] isEqual: [arrayClass arrayWithObjects:
	    @"0", @"Bar", @"Baz", @"Foo", @"z", nil]] &&

	    [[m[1] sortedArrayWithOptions: OF_ARRAY_SORT_DESCENDING]
	    isEqual: [arrayClass arrayWithObjects:
	    @"z", @"Foo", @"Baz", @"Bar", @"0", nil]])

	EXPECT_EXCEPTION(@"Detect out of range in -[objectAtIndex:]",
	    OFOutOfRangeException, [a[0] objectAtIndex: [a[0] count]])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeObjectsInRange:]",







>
|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

	m[1] = [[a[0] mutableCopy] autorelease];
	[m[1] addObject: @"0"];
	[m[1] addObject: @"z"];
	TEST(@"-[sortedArray]",
	    [[m[1] sortedArray] isEqual: [arrayClass arrayWithObjects:
	    @"0", @"Bar", @"Baz", @"Foo", @"z", nil]] &&
	    [[m[1] sortedArrayUsingSelector: @selector(compare:)
				    options: OF_ARRAY_SORT_DESCENDING]
	    isEqual: [arrayClass arrayWithObjects:
	    @"z", @"Foo", @"Baz", @"Bar", @"0", nil]])

	EXPECT_EXCEPTION(@"Detect out of range in -[objectAtIndex:]",
	    OFOutOfRangeException, [a[0] objectAtIndex: [a[0] count]])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeObjectsInRange:]",