ObjFW  Check-in [5b57beeba6]

Overview
Comment:Rename all types in OFList
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | new-naming-convention
Files: files | file ages | folders
SHA3-256: 5b57beeba643e40de6092b44c7e82e85a8867c33dddf349621f2f4997a9b637b
User & Date: js on 2021-04-17 05:45:50
Other Links: branch diff | manifest | tags
Context
2021-04-17
12:30
of_socket_t -> OFSocketHandle check-in: c4ae62dd34 user: js tags: new-naming-convention
05:45
Rename all types in OFList check-in: 5b57beeba6 user: js tags: new-naming-convention
05:28
Rename all types in OFTarArchive(Entry).h check-in: 795618c69f user: js tags: new-naming-convention
Changes

Modified src/OFList.h from [36d06c646e] to [0c075514d1].

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







-
+

-
+

-
+

-
-
+
+

-
+

-
+

-
+















-
-
+
+

-
+






-
+
-












-
+
-




















-
+

-
+

-
+





-
+

-
+

-
+





-
-
-
+
+
+

-
+

-
-
+
+





-
+

-
+

-
+

-
-
+
+




-
+

-
+







#import "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

typedef struct of_list_object_t of_list_object_t;
typedef struct OFListItem OFListItem;
/**
 * @struct of_list_object_t OFList.h ObjFW/OFList.h
 * @struct OFListItem OFList.h ObjFW/OFList.h
 *
 * @brief A list object.
 * @brief A list item.
 *
 * A struct that contains a pointer to the next list object, the previous list
 * object and the object.
 * A struct that contains a pointer to the next list item, the previous list
 * item and the object.
 */
struct of_list_object_t {
struct OFListItem {
	/** A pointer to the next list object in the list */
	of_list_object_t *_Nullable next;
	OFListItem *_Nullable next;
	/** A pointer to the previous list object in the list */
	of_list_object_t *_Nullable previous;
	OFListItem *_Nullable previous;
	/** The object for the list object */
	id __unsafe_unretained object;
};

/**
 * @class OFList OFList.h ObjFW/OFList.h
 *
 * @brief A class which provides easy to use double-linked lists.
 */
@interface OFList OF_GENERIC(ObjectType): OFObject <OFCopying, OFCollection,
    OFSerialization>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
{
	of_list_object_t *_Nullable _firstListObject;
	of_list_object_t *_Nullable _lastListObject;
	OFListItem *_Nullable _firstListItem;
	OFListItem *_Nullable _lastListItem;
	size_t _count;
	unsigned long  _mutations;
	unsigned long _mutations;
	OF_RESERVE_IVARS(OFList, 4)
}

/**
 * @brief The first list object of the list.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFListItem *firstListItem;
    of_list_object_t *firstListObject;

/**
 * @brief The first object of the list or `nil`.
 *
 * @warning The returned object is *not* retained and autoreleased for
 *	    performance reasons!
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) ObjectType firstObject;

/**
 * @brief The last list object of the list.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFListItem *lastListItem;
    of_list_object_t *lastListObject;

/**
 * @brief The last object of the list or `nil`.
 *
 * @warning The returned object is *not* retained and autoreleased for
 *	    performance reasons!
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) ObjectType lastObject;

/**
 * @brief Creates a new OFList.
 *
 * @return A new autoreleased OFList
 */
+ (instancetype)list;

/**
 * @brief Appends an object to the list.
 *
 * @param object The object to append
 * @return An of_list_object_t, needed to identify the object inside the list.
 * @return An OFListItem, needed to identify the object inside the list.
 *	   For example, if you want to remove an object from the list, you need
 *	   its of_list_object_t.
 *	   its OFListItem.
 */
- (of_list_object_t *)appendObject: (ObjectType)object;
- (OFListItem *)appendObject: (ObjectType)object;

/**
 * @brief Prepends an object to the list.
 *
 * @param object The object to prepend
 * @return An of_list_object_t, needed to identify the object inside the list.
 * @return An OFListItem, needed to identify the object inside the list.
 *	   For example, if you want to remove an object from the list, you need
 *	   its of_list_object_t.
 *	   its OFListItem.
 */
- (of_list_object_t *)prependObject: (ObjectType)object;
- (OFListItem *)prependObject: (ObjectType)object;

/**
 * @brief Inserts an object before another list object.
 *
 * @param object The object to insert
 * @param listObject The of_list_object_t of the object before which it should
 *	  be inserted
 * @return An of_list_object_t, needed to identify the object inside the list.
 * @param listItem The OFListItem of the object before which it should be
 *		   inserted
 * @return An OFListItem, needed to identify the object inside the list.
 *	   For example, if you want to remove an object from the list, you need
 *	   its of_list_object_t.
 *	   its OFListItem.
 */
- (of_list_object_t *)insertObject: (ObjectType)object
		  beforeListObject: (of_list_object_t *)listObject;
- (OFListItem *)insertObject: (ObjectType)object
	      beforeListItem: (OFListItem *)listItem;

/**
 * @brief Inserts an object after another list object.
 *
 * @param object The object to insert
 * @param listObject The of_list_object_t of the object after which it should be
 * @param listItem The OFListItem of the object after which it should be
 *	  inserted
 * @return An of_list_object_t, needed to identify the object inside the list.
 * @return An OFListItem, needed to identify the object inside the list.
 *	   For example, if you want to remove an object from the list, you need
 *	   its of_list_object_t.
 *	   its OFListItem.
 */
- (of_list_object_t *)insertObject: (ObjectType)object
		   afterListObject: (of_list_object_t *)listObject;
- (OFListItem *)insertObject: (ObjectType)object
	       afterListItem: (OFListItem *)listItem;

/**
 * @brief Removes the object with the specified list object from the list.
 *
 * @param listObject The list object returned by append / prepend
 * @param listItem The list object returned by append / prepend
 */
- (void)removeListObject: (of_list_object_t *)listObject;
- (void)removeListItem: (OFListItem *)listItem;

/**
 * @brief Checks whether the list contains an object equal to the specified
 *	  object.
 *
 * @param object The object which is checked for being in the list
 * @return A boolean whether the list contains the specified object

Modified src/OFList.m from [eaa8494459] to [ce0d3e5241].

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







-
+









-
+
-







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

OF_DIRECT_MEMBERS
@interface OFListEnumerator: OFEnumerator
{
	OFList *_list;
	of_list_object_t *_Nullable _current;
	OFListItem *_Nullable _current;
	unsigned long _mutations;
	unsigned long *_Nullable _mutationsPtr;
}

- (instancetype)initWithList: (OFList *)list
	    mutationsPointer: (unsigned long *)mutationsPtr;
@end

@implementation OFList
@synthesize firstListObject = _firstListObject;
@synthesize firstListItem = _firstListItem, lastListItem = _lastListItem;
@synthesize lastListObject = _lastListObject;

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

- (instancetype)initWithSerialization: (OFXMLElement *)element
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
357
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







-
+

-
-
+








-
+

-
+

-
-
-
-
+
+
+
+

-
-
+
+

-
+

-
-
+
+




-
+


-
+

-
+

-
-
-
-
+
+
+

-
-
+
+

-
-
-
+
+
+




-
+


-
-
+
+

-
+

-
-
-
-
+
+
+

-
-
+
+

-
+

-
-
+
+




-
+


-
-
+
+

-
+

-
-
-
-
+
+
+

-
-
+
+

-
+

-
-
+
+




-
+


-
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+




-
-
+
+




-
+




-
+










-
+












-
+
















-
-
+











-
-
+








-
+



-
-
+





-
+





-
+

-
+



-
+

-
-
-
-
+
+
+
+

-
-
+
+

-
+



-
+






-
+










-
+

















-
+







	}

	return self;
}

- (void)dealloc
{
	of_list_object_t *next;
	OFListItem *next;

	for (of_list_object_t *iter = _firstListObject;
	    iter != NULL; iter = next) {
	for (OFListItem *iter = _firstListItem; iter != NULL; iter = next) {
		[iter->object release];
		next = iter->next;
		free(iter);
	}

	[super dealloc];
}

- (of_list_object_t *)appendObject: (id)object
- (OFListItem *)appendObject: (id)object
{
	of_list_object_t *listObject;
	OFListItem *listItem;

	listObject = of_alloc(1, sizeof(of_list_object_t));
	listObject->object = [object retain];
	listObject->next = NULL;
	listObject->previous = _lastListObject;
	listItem = of_alloc(1, sizeof(OFListItem));
	listItem->object = [object retain];
	listItem->next = NULL;
	listItem->previous = _lastListItem;

	if (_lastListObject != NULL)
		_lastListObject->next = listObject;
	if (_lastListItem != NULL)
		_lastListItem->next = listItem;

	_lastListObject = listObject;
	_lastListItem = listItem;

	if (_firstListObject == NULL)
		_firstListObject = listObject;
	if (_firstListItem == NULL)
		_firstListItem = listItem;

	_count++;
	_mutations++;

	return listObject;
	return listItem;
}

- (of_list_object_t *)prependObject: (id)object
- (OFListItem *)prependObject: (id)object
{
	of_list_object_t *listObject;
	OFListItem *listItem = of_alloc(1, sizeof(OFListItem));

	listObject = of_alloc(1, sizeof(of_list_object_t));
	listObject->object = [object retain];
	listObject->next = _firstListObject;
	listObject->previous = NULL;
	listItem->object = [object retain];
	listItem->next = _firstListItem;
	listItem->previous = NULL;

	if (_firstListObject != NULL)
		_firstListObject->previous = listObject;
	if (_firstListItem != NULL)
		_firstListItem->previous = listItem;

	_firstListObject = listObject;
	if (_lastListObject == NULL)
		_lastListObject = listObject;
	_firstListItem = listItem;
	if (_lastListItem == NULL)
		_lastListItem = listItem;

	_count++;
	_mutations++;

	return listObject;
	return listItem;
}

- (of_list_object_t *)insertObject: (id)object
		  beforeListObject: (of_list_object_t *)listObject
- (OFListItem *)insertObject: (id)object
	      beforeListItem: (OFListItem *)listItem
{
	of_list_object_t *newListObject;
	OFListItem *newListItem = of_alloc(1, sizeof(OFListItem));

	newListObject = of_alloc(1, sizeof(of_list_object_t));
	newListObject->object = [object retain];
	newListObject->next = listObject;
	newListObject->previous = listObject->previous;
	newListItem->object = [object retain];
	newListItem->next = listItem;
	newListItem->previous = listItem->previous;

	if (listObject->previous != NULL)
		listObject->previous->next = newListObject;
	if (listItem->previous != NULL)
		listItem->previous->next = newListItem;

	listObject->previous = newListObject;
	listItem->previous = newListItem;

	if (listObject == _firstListObject)
		_firstListObject = newListObject;
	if (listItem == _firstListItem)
		_firstListItem = newListItem;

	_count++;
	_mutations++;

	return newListObject;
	return newListItem;
}

- (of_list_object_t *)insertObject: (id)object
		   afterListObject: (of_list_object_t *)listObject
- (OFListItem *)insertObject: (id)object
	       afterListItem: (OFListItem *)listItem
{
	of_list_object_t *newListObject;
	OFListItem *newListItem = of_alloc(1, sizeof(OFListItem));

	newListObject = of_alloc(1, sizeof(of_list_object_t));
	newListObject->object = [object retain];
	newListObject->next = listObject->next;
	newListObject->previous = listObject;
	newListItem->object = [object retain];
	newListItem->next = listItem->next;
	newListItem->previous = listItem;

	if (listObject->next != NULL)
		listObject->next->previous = newListObject;
	if (listItem->next != NULL)
		listItem->next->previous = newListItem;

	listObject->next = newListObject;
	listItem->next = newListItem;

	if (listObject == _lastListObject)
		_lastListObject = newListObject;
	if (listItem == _lastListItem)
		_lastListItem = newListItem;

	_count++;
	_mutations++;

	return newListObject;
	return newListItem;
}

- (void)removeListObject: (of_list_object_t *)listObject
- (void)removeListItem: (OFListItem *)listItem
{
	if (listObject->previous != NULL)
		listObject->previous->next = listObject->next;
	if (listObject->next != NULL)
		listObject->next->previous = listObject->previous;
	if (listItem->previous != NULL)
		listItem->previous->next = listItem->next;
	if (listItem->next != NULL)
		listItem->next->previous = listItem->previous;

	if (_firstListObject == listObject)
		_firstListObject = listObject->next;
	if (_lastListObject == listObject)
		_lastListObject = listObject->previous;
	if (_firstListItem == listItem)
		_firstListItem = listItem->next;
	if (_lastListItem == listItem)
		_lastListItem = listItem->previous;

	_count--;
	_mutations++;

	[listObject->object release];
	free(listObject);
	[listItem->object release];
	free(listItem);
}

- (id)firstObject
{
	return (_firstListObject != NULL ? _firstListObject->object : nil);
	return (_firstListItem != NULL ? _firstListItem->object : nil);
}

- (id)lastObject
{
	return (_lastListObject != NULL ? _lastListObject->object : nil);
	return (_lastListItem != NULL ? _lastListItem->object : nil);
}

- (size_t)count
{
	return _count;
}

- (bool)isEqual: (id)object
{
	OFList *list;
	of_list_object_t *iter, *iter2;
	OFListItem *iter, *iter2;

	if (object == self)
		return true;

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

	list = object;

	if (list.count != _count)
		return false;

	for (iter = _firstListObject, iter2 = list.firstListObject;
	for (iter = _firstListItem, iter2 = list.firstListItem;
	    iter != NULL && iter2 != NULL;
	    iter = iter->next, iter2 = iter2->next)
		if (![iter->object isEqual: iter2->object])
			return false;

	/* One is bigger than the other even though we checked the count */
	assert(iter == NULL && iter2 == NULL);

	return true;
}

- (bool)containsObject: (id)object
{
	if (_count == 0)
		return false;

	for (of_list_object_t *iter = _firstListObject;
	    iter != NULL; iter = iter->next)
	for (OFListItem *iter = _firstListItem; iter != NULL; iter = iter->next)
		if ([iter->object isEqual: object])
			return true;

	return false;
}

- (bool)containsObjectIdenticalTo: (id)object
{
	if (_count == 0)
		return false;

	for (of_list_object_t *iter = _firstListObject;
	    iter != NULL; iter = iter->next)
	for (OFListItem *iter = _firstListItem; iter != NULL; iter = iter->next)
		if (iter->object == object)
			return true;

	return false;
}

- (void)removeAllObjects
{
	of_list_object_t *next;
	OFListItem *next;

	_mutations++;

	for (of_list_object_t *iter = _firstListObject;
	    iter != NULL; iter = next) {
	for (OFListItem *iter = _firstListItem; iter != NULL; iter = next) {
		[iter->object release];
		next = iter->next;
		free(iter);
	}

	_firstListObject = _lastListObject = NULL;
	_firstListItem = _lastListItem = NULL;
}

- (id)copy
{
	OFList *copy = [[[self class] alloc] init];
	of_list_object_t *listObject, *previous;
	OFListItem *listItem, *previous;

	listObject = NULL;
	listItem = NULL;
	previous = NULL;

	@try {
		for (of_list_object_t *iter = _firstListObject;
		for (OFListItem *iter = _firstListItem;
		    iter != NULL; iter = iter->next) {
			listObject = of_alloc(1, sizeof(of_list_object_t));
			listObject->object = [iter->object retain];
			listObject->next = NULL;
			listObject->previous = previous;
			listItem = of_alloc(1, sizeof(OFListItem));
			listItem->object = [iter->object retain];
			listItem->next = NULL;
			listItem->previous = previous;

			if (copy->_firstListObject == NULL)
				copy->_firstListObject = listObject;
			if (copy->_firstListItem == NULL)
				copy->_firstListItem = listItem;
			if (previous != NULL)
				previous->next = listObject;
				previous->next = listItem;

			copy->_count++;

			previous = listObject;
			previous = listItem;
		}
	} @catch (id e) {
		[copy release];
		@throw e;
	}

	copy->_lastListObject = listObject;
	copy->_lastListItem = listItem;

	return copy;
}

- (unsigned long)hash
{
	uint32_t hash;

	OF_HASH_INIT(hash);

	for (of_list_object_t *iter = _firstListObject;
	for (OFListItem *iter = _firstListItem;
	    iter != NULL; iter = iter->next)
		OF_HASH_ADD_HASH(hash, [iter->object hash]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

- (OFString *)description
{
	OFMutableString *ret;

	if (_count == 0)
		return @"[]";

	ret = [OFMutableString stringWithString: @"[\n"];

	for (of_list_object_t *iter = _firstListObject;
	for (OFListItem *iter = _firstListItem;
	    iter != NULL; iter = iter->next) {
		void *pool = objc_autoreleasePoolPush();

		[ret appendString: [iter->object description]];

		if (iter->next != NULL)
			[ret appendString: @",\n"];
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
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







-
+















-
+

-
+





-
+




-
+


-
-
+
+


-
+



















-
+








- (OFXMLElement *)XMLElementBySerializing
{
	OFXMLElement *element =
	    [OFXMLElement elementWithName: self.className
				namespace: OF_SERIALIZATION_NS];

	for (of_list_object_t *iter = _firstListObject;
	for (OFListItem *iter = _firstListItem;
	    iter != NULL; iter = iter->next) {
		void *pool = objc_autoreleasePoolPush();

		[element addChild: [iter->object XMLElementBySerializing]];

		objc_autoreleasePoolPop(pool);
	}

	return element;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{
	of_list_object_t *listObject;
	OFListItem *listItem;

	memcpy(&listObject, state->extra, sizeof(listObject));
	memcpy(&listItem, state->extra, sizeof(listItem));

	state->itemsPtr = objects;
	state->mutationsPtr = &_mutations;

	if (state->state == 0) {
		listObject = _firstListObject;
		listItem = _firstListItem;
		state->state = 1;
	}

	for (int i = 0; i < count; i++) {
		if (listObject == NULL)
		if (listItem == NULL)
			return i;

		objects[i] = listObject->object;
		listObject = listObject->next;
		objects[i] = listItem->object;
		listItem = listItem->next;
	}

	memcpy(state->extra, &listObject, sizeof(listObject));
	memcpy(state->extra, &listItem, sizeof(listItem));

	return count;
}

- (OFEnumerator *)objectEnumerator
{
	return [[[OFListEnumerator alloc] initWithList: self
				      mutationsPointer: &_mutations]
	    autorelease];
}
@end

@implementation OFListEnumerator
- (instancetype)initWithList: (OFList *)list
	    mutationsPointer: (unsigned long *)mutationsPtr
{
	self = [super init];

	_list = [list retain];
	_current = _list.firstListObject;
	_current = _list.firstListItem;
	_mutations = *mutationsPtr;
	_mutationsPtr = mutationsPtr;

	return self;
}

- (void)dealloc

Modified src/OFRunLoop.m from [d30798d206] to [4c3afea7cc].

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







-
+






-
+






-
+

-
+







	OFList OF_GENERIC(OF_KINDOF(OFRunLoopReadQueueItem *)) *queue =
	    [[_readQueues objectForKey: object] retain];

	assert(queue != nil);

	@try {
		if (![queue.firstObject handleObject: object]) {
			of_list_object_t *listObject = queue.firstListObject;
			OFListItem *listItem = queue.firstListItem;

			/*
			 * The handler might have called -[cancelAsyncRequests]
			 * so that our queue is now empty, in which case we
			 * should do nothing.
			 */
			if (listObject != NULL) {
			if (listItem != NULL) {
				/*
				 * Make sure we keep the target until after we
				 * are done removing the object. The reason for
				 * this is that the target might call
				 * -[cancelAsyncRequests] in its dealloc.
				 */
				[[listObject->object retain] autorelease];
				[[listItem->object retain] autorelease];

				[queue removeListObject: listObject];
				[queue removeListItem: listItem];

				if (queue.count == 0) {
					[_kernelEventObserver
					    removeObjectForReading: object];
					[_readQueues
					    removeObjectForKey: object];
				}
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
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







-
+






-
+






-
+

-
+







	 */
	OFList *queue = [[_writeQueues objectForKey: object] retain];

	assert(queue != nil);

	@try {
		if (![queue.firstObject handleObject: object]) {
			of_list_object_t *listObject = queue.firstListObject;
			OFListItem *listItem = queue.firstListItem;

			/*
			 * The handler might have called -[cancelAsyncRequests]
			 * so that our queue is now empty, in which case we
			 * should do nothing.
			 */
			if (listObject != NULL) {
			if (listItem != NULL) {
				/*
				 * Make sure we keep the target until after we
				 * are done removing the object. The reason for
				 * this is that the target might call
				 * -[cancelAsyncRequests] in its dealloc.
				 */
				[[listObject->object retain] autorelease];
				[[listItem->object retain] autorelease];

				[queue removeListObject: listObject];
				[queue removeListItem: listItem];

				if (queue.count == 0) {
					[_kernelEventObserver
					    removeObjectForWriting: object];
					[_writeQueues
					    removeObjectForKey: object];
				}
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426


1427
1428

1429
1430
1431
1432
1433
1434
1435
1416
1417
1418
1419
1420
1421
1422




1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433







-
-
-
-
+
+

-
+







	if (state == nil)
		return;

#ifdef OF_HAVE_THREADS
	[state->_timersQueueMutex lock];
	@try {
#endif
		of_list_object_t *iter;

		for (iter = state->_timersQueue.firstListObject; iter != NULL;
		    iter = iter->next) {
		for (OFListItem *iter = state->_timersQueue.firstListItem;
		    iter != NULL; iter = iter->next) {
			if ([iter->object isEqual: timer]) {
				[state->_timersQueue removeListObject: iter];
				[state->_timersQueue removeListItem: iter];
				break;
			}
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		[state->_timersQueueMutex unlock];
	}
1575
1576
1577
1578
1579
1580
1581
1582
1583


1584
1585

1586
1587

1588
1589
1590
1591

1592
1593
1594
1595
1596
1597
1598
1573
1574
1575
1576
1577
1578
1579


1580
1581
1582

1583
1584

1585
1586
1587
1588

1589
1590
1591
1592
1593
1594
1595
1596







-
-
+
+

-
+

-
+



-
+







		for (;;) {
			OFTimer *timer;

#ifdef OF_HAVE_THREADS
			[state->_timersQueueMutex lock];
			@try {
#endif
				of_list_object_t *listObject =
				    state->_timersQueue.firstListObject;
				OFListItem *listItem =
				    state->_timersQueue.firstListItem;

				if (listObject != NULL && [listObject->object
				if (listItem != NULL && [listItem->object
				    fireDate].timeIntervalSinceNow <= 0) {
					timer = [[listObject->object
					timer = [[listItem->object
					    retain] autorelease];

					[state->_timersQueue
					    removeListObject: listObject];
					    removeListItem: listItem];

					[timer of_setInRunLoop: nil mode: nil];
				} else
					break;
#ifdef OF_HAVE_THREADS
			} @finally {
				[state->_timersQueueMutex unlock];

Modified src/OFSortedList.h from [d2fd296ecb] to [10d4fe8869].

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







-
-
-
-
+
+
+
+

-
-
+
+








-
+






#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
{
	OF_RESERVE_IVARS(OFSortedList, 4)
}

- (of_list_object_t *)appendObject: (ObjectType)object OF_UNAVAILABLE;
- (of_list_object_t *)prependObject: (ObjectType)object OF_UNAVAILABLE;
- (of_list_object_t *)insertObject: (ObjectType)object
		  beforeListObject: (of_list_object_t *)listObject
- (OFListItem *)appendObject: (ObjectType)object OF_UNAVAILABLE;
- (OFListItem *)prependObject: (ObjectType)object OF_UNAVAILABLE;
- (OFListItem *)insertObject: (ObjectType)object
	      beforeListItem: (OFListItem *)listItem
    OF_UNAVAILABLE;
- (of_list_object_t *)insertObject: (ObjectType)object
		   afterListObject: (of_list_object_t *)listObject
- (OFListItem *)insertObject: (ObjectType)object
	       afterListItem: (OFListItem *)listItem
    OF_UNAVAILABLE;

/**
 * @brief Inserts the object to the list while keeping the list sorted.
 *
 * @param object The object to insert
 * @return The list object for the object just added
 */
- (of_list_object_t *)insertObject: (ObjectType <OFComparing>)object;
- (OFListItem *)insertObject: (ObjectType <OFComparing>)object;
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# undef ObjectType
#endif
@end

OF_ASSUME_NONNULL_END

Modified src/OFSortedList.m from [2de4cf3237] to [228aa13ba0].

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







-
+




-
+




-
-
+
+




-
-
+
+




-
+

-
+

-
+

-
+
-





 */

#include "config.h"

#import "OFSortedList.h"

@implementation OFSortedList
- (of_list_object_t *)appendObject: (id)object
- (OFListItem *)appendObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (of_list_object_t *)prependObject: (id)object
- (OFListItem *)prependObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (of_list_object_t *)insertObject: (id)object
		  beforeListObject: (of_list_object_t *)listObject
- (OFListItem *)insertObject: (id)object
	      beforeListItem: (OFListItem *)listItem
{
	OF_UNRECOGNIZED_SELECTOR
}

- (of_list_object_t *)insertObject: (id)object
		   afterListObject: (of_list_object_t *)listObject
- (OFListItem *)insertObject: (id)object
	       afterListItem: (OFListItem *)listItem
{
	OF_UNRECOGNIZED_SELECTOR
}

- (of_list_object_t *)insertObject: (id <OFComparing>)object
- (OFListItem *)insertObject: (id <OFComparing>)object
{
	of_list_object_t *iter;
	OFListItem *iter;

	for (iter = _lastListObject; iter != NULL; iter = iter->previous) {
	for (iter = _lastListItem; iter != NULL; iter = iter->previous) {
		if ([object compare: iter->object] != OFOrderedAscending)
			return [super insertObject: object
			return [super insertObject: object afterListItem: iter];
				   afterListObject: iter];
	}

	return [super prependObject: object];
}
@end

Modified src/OFThreadPool.m from [ae8a5813e0] to [62afef694d].

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







-
+






-
+

-
+







-
+


-
-
+
+







	pool = objc_autoreleasePoolPush();

	for (;;) {
		OFThreadPoolJob *job;

		[_queueCondition lock];
		@try {
			of_list_object_t *listObject;
			OFListItem *listItem;

			if (_terminate) {
				objc_autoreleasePoolPop(pool);
				return nil;
			}

			listObject = _queue.firstListObject;
			listItem = _queue.firstListItem;

			while (listObject == NULL) {
			while (listItem == NULL) {
				[_queueCondition wait];

				if (_terminate) {
					objc_autoreleasePoolPop(pool);
					return nil;
				}

				listObject = _queue.firstListObject;
				listItem = _queue.firstListItem;
			}

			job = [[listObject->object retain] autorelease];
			[_queue removeListObject: listObject];
			job = [[listItem->object retain] autorelease];
			[_queue removeListItem: listItem];
		} @finally {
			[_queueCondition unlock];
		}

		if (_terminate) {
			objc_autoreleasePoolPop(pool);
			return nil;

Modified tests/OFListTests.m from [6f825fa0b7] to [045f6f7c6a].

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







-
+









-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+
-
-
+

-
+

-
-
+
+













-
-
-
+
+
+








-
+



-
+


-
+








-
+






-
+




-
+


-
+













-
+











@implementation TestsAppDelegate (OFListTests)
- (void)listTests
{
	void *pool = objc_autoreleasePoolPush();
	OFList *list;
	OFEnumerator *enumerator;
	of_list_object_t *loe;
	OFListItem *iter;
	OFString *obj;
	size_t i;
	bool ok;

	TEST(@"+[list]", (list = [OFList list]))

	TEST(@"-[appendObject:]", [list appendObject: strings[0]] &&
	    [list appendObject: strings[1]] && [list appendObject: strings[2]])

	TEST(@"-[firstListObject]",
	    [list.firstListObject->object isEqual: strings[0]])
	TEST(@"-[firstListItem]",
	    [list.firstListItem->object isEqual: strings[0]])

	TEST(@"-[firstListObject]->next",
	    [list.firstListObject->next->object isEqual: strings[1]])
	TEST(@"-[firstListItem]->next",
	    [list.firstListItem->next->object isEqual: strings[1]])

	TEST(@"-[lastListObject]",
	    [list.lastListObject->object isEqual: strings[2]])
	TEST(@"-[lastListItem]",
	    [list.lastListItem->object isEqual: strings[2]])

	TEST(@"-[lastListObject]->previous",
	    [list.lastListObject->previous->object isEqual: strings[1]])
	TEST(@"-[lastListItem]->previous",
	    [list.lastListItem->previous->object isEqual: strings[1]])

	TEST(@"-[removeListObject:]",
	    R([list removeListObject: list.lastListObject]) &&
	    [list.lastListObject->object isEqual: strings[1]] &&
	    R([list removeListObject: list.firstListObject]) &&
	    [list.firstListObject->object isEqual: list.lastListObject->object])
	TEST(@"-[removeListItem:]",
	    R([list removeListItem: list.lastListItem]) &&
	    [list.lastListItem->object isEqual: strings[1]] &&
	    R([list removeListItem: list.firstListItem]) &&
	    [list.firstListItem->object isEqual: list.lastListItem->object])

	TEST(@"-[insertObject:beforeListObject:]",
	    [list insertObject: strings[0]
	TEST(@"-[insertObject:beforeListItem:]",
	    [list insertObject: strings[0] beforeListItem: list.lastListItem] &&
	      beforeListObject: list.lastListObject] &&
	    [list.lastListObject->previous->object isEqual: strings[0]])
	    [list.lastListItem->previous->object isEqual: strings[0]])

	TEST(@"-[insertObject:afterListObject:]",
	TEST(@"-[insertObject:afterListItem:]",
	    [list insertObject: strings[2]
	       afterListObject: list.firstListObject->next] &&
	    [list.lastListObject->object isEqual: strings[2]])
		 afterListItem: list.firstListItem->next] &&
	    [list.lastListItem->object isEqual: strings[2]])

	TEST(@"-[count]", list.count == 3)

	TEST(@"-[containsObject:]",
	    [list containsObject: strings[1]] &&
	    ![list containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [list containsObjectIdenticalTo: strings[1]] &&
	    ![list containsObjectIdenticalTo:
	    [OFString stringWithString: strings[1]]])

	TEST(@"-[copy]", (list = [[list copy] autorelease]) &&
	    [list.firstListObject->object isEqual: strings[0]] &&
	    [list.firstListObject->next->object isEqual: strings[1]] &&
	    [list.lastListObject->object isEqual: strings[2]])
	    [list.firstListItem->object isEqual: strings[0]] &&
	    [list.firstListItem->next->object isEqual: strings[1]] &&
	    [list.lastListItem->object isEqual: strings[2]])

	TEST(@"-[isEqual:]", [list isEqual: [[list copy] autorelease]])

	TEST(@"-[description]",
	    [list.description isEqual: @"[\n\tFoo,\n\tBar,\n\tBaz\n]"])

	TEST(@"-[objectEnumerator]", (enumerator = [list objectEnumerator]))

	loe = list.firstListObject;
	iter = list.firstListItem;
	i = 0;
	ok = true;
	while ((obj = [enumerator nextObject]) != nil) {
		if (![obj isEqual: loe->object])
		if (![obj isEqual: iter->object])
			ok = false;

		loe = loe->next;
		iter = iter->next;
		i++;
	}

	if (list.count != i)
		ok = false;

	TEST(@"OFEnumerator's -[nextObject]", ok);

	[list removeListObject: list.firstListObject];
	[list removeListItem: list.firstListItem];

	EXPECT_EXCEPTION(@"Detection of mutation during enumeration",
	    OFEnumerationMutationException, [enumerator nextObject])

	[list prependObject: strings[0]];

	loe = list.firstListObject;
	iter = list.firstListItem;
	i = 0;
	ok = true;

	for (OFString *object in list) {
		if (![object isEqual: loe->object])
		if (![object isEqual: iter->object])
			ok = false;

		loe = loe->next;
		iter = iter->next;
		i++;
	}

	if (list.count != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *object in list) {
			(void)object;

			[list removeListObject: list.lastListObject];
			[list removeListItem: list.lastListItem];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	objc_autoreleasePoolPop(pool);
}
@end