ObjFW  Check-in [c85ff8d35a]

Overview
Comment:OFDataArray: Improve API.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: c85ff8d35a9a7fb28a142a4705dbbb9fd7847c8ec41c551aeb098fa890da3bbf
User & Date: js on 2012-12-15 17:52:20
Other Links: manifest | tags
Context
2012-12-15
19:36
OFHTTPServer: Fix handling of Host:. check-in: 2fb248a952 user: js tags: trunk
17:52
OFDataArray: Improve API. check-in: c85ff8d35a user: js tags: trunk
2012-12-14
01:46
Add -[description] for OFHTTPRequest(Result). check-in: c3d536d43c user: js tags: trunk
Changes

Modified src/OFArray_adjacent.m from [78c03c8d5c] to [72c1eebe96].

107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121







-
+







		@throw e;
	}

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

		[array addItemsFromCArray: objects
		[array addItems: objects
				    count: count];
	} @catch (id e) {
		for (i = 0; i < count; i++)
			[objects[i] release];

		/* Prevent double-release of objects */
		[array release];
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158







-
+







			[objects[i] retain];
		}

		if (!ok)
			@throw [OFInvalidArgumentException
			    exceptionWithClass: [self class]];

		[array addItemsFromCArray: objects
		[array addItems: objects
				    count: count];
	} @catch (id e) {
		size_t i;

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

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







-
+















-
+


















-
+

















-
+



















-
+







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

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

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

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

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

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > count)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

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

- (size_t)indexOfObject: (id)object
{
	id *objects;
	size_t i, count;

	if (object == nil)
		return OF_NOT_FOUND;

	objects = [array cArray];
	objects = [array items];
	count = [array count];

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

	return OF_NOT_FOUND;
}

- (size_t)indexOfObjectIdenticalTo: (id)object
{
	id *objects;
	size_t i, count;

	if (object == nil)
		return OF_NOT_FOUND;

	objects = [array cArray];
	objects = [array items];
	count = [array count];

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

	return OF_NOT_FOUND;
}


- (OFArray*)objectsInRange: (of_range_t)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > [array count])
		@throw [OFOutOfRangeException
		    exceptionWithClass: [self class]];

	if ([self isKindOfClass: [OFMutableArray class]])
		return [OFArray
		    arrayWithObjects: (id*)[array cArray] + range.location
		    arrayWithObjects: (id*)[array items] + range.location
			       count: range.length];

	return [OFArray_adjacentSubarray arrayWithArray: self
						  range: range];
}

- (BOOL)isEqual: (id)object
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
358
359
360
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357
358
359
360







-
+











-
+
















-
+










-
+










	otherArray = object;

	count = [array count];

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

	objects = [array cArray];
	objects = [array items];
	otherObjects = [otherArray objects];

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

	return YES;
}

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

	OF_HASH_INIT(hash);

	for (i = 0; i < count; i++)
		OF_HASH_ADD_HASH(hash, [objects[i] hash]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

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

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

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

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

	[array release];

	[super dealloc];
}
@end

Modified src/OFDataArray+Hashing.m from [d10ff72ecd] to [f44a85040b].

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







-
+

















-
+










-
+

















-
+


{
	void *pool = objc_autoreleasePoolPush();
	OFMD5Hash *hash = [OFMD5Hash hash];
	uint8_t *digest;
	char cString[OF_MD5_DIGEST_SIZE * 2];
	size_t i;

	[hash updateWithBuffer: data
	[hash updateWithBuffer: items
			length: count * itemSize];
	digest = [hash digest];

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

		high = digest[i] >> 4;
		low  = digest[i] & 0x0F;

		cString[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0');
		cString[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0');
	}

	objc_autoreleasePoolPop(pool);

	return [OFString stringWithCString: cString
				  encoding: OF_STRING_ENCODING_ASCII
				    length: 32];
				    length: OF_MD5_DIGEST_SIZE * 2];
}

- (OFString*)SHA1Hash
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *hash = [OFSHA1Hash hash];
	uint8_t *digest;
	char cString[OF_SHA1_DIGEST_SIZE * 2];
	size_t i;

	[hash updateWithBuffer: data
	[hash updateWithBuffer: items
			length: count * itemSize];
	digest = [hash digest];

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

		high = digest[i] >> 4;
		low  = digest[i] & 0x0F;

		cString[i * 2] = (high > 9 ? high - 10 + 'a' : high + '0');
		cString[i * 2 + 1] = (low > 9 ? low - 10 + 'a' : low + '0');
	}

	objc_autoreleasePoolPop(pool);

	return [OFString stringWithCString: cString
				  encoding: OF_STRING_ENCODING_ASCII
				    length: 40];
				    length: OF_SHA1_DIGEST_SIZE * 2];
}
@end

Modified src/OFDataArray.h from [ebbd8162b6] to [fbee0f546e].

27
28
29
30
31
32
33
34

35
36
37
38
39
40

41
42
43
44
45
46
47
27
28
29
30
31
32
33

34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+





-
+







 * OFBigDataArray, which allocates the memory in pages rather than in bytes.
 *
 * For security reasons, serialization and deserialization is only implemented
 * for OFDataArrays with item size 1.
 */
@interface OFDataArray: OFObject <OFCopying, OFComparing, OFSerialization>
{
	uint8_t *data;
	uint8_t *items;
	size_t count;
	size_t itemSize;
}

#ifdef OF_HAVE_PROPERTIES
@property (readonly, getter=cArray) void *data;
@property (readonly) void *items;
@property (readonly) size_t count;
@property (readonly) size_t itemSize;
#endif

/*!
 * @brief Creates a new OFDataArray with an item size of 1.
 *
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
172







-
+








-
+







 * @brief Returns the size of each item in the OFDataArray in bytes.
 *
 * @return The size of each item in the OFDataArray in bytes
 */
- (size_t)itemSize;

/*!
 * @brief Returns all elements of the OFDataArray as a C array.
 * @brief Returns all items of the OFDataArray as a C array.
 *
 * @warning The pointer is only valid until the OFDataArray is changed!
 *
 * Modifying the returned array directly is allowed and will change the contents
 * of the data array.
 *
 * @return All elements of the OFDataArray as a C array
 */
- (void*)cArray OF_RETURNS_INNER_POINTER;
- (void*)items OF_RETURNS_INNER_POINTER;

/*!
 * @brief Returns a specific item of the OFDataArray.
 *
 * @param index The number of the item to return
 * @return The specified item of the OFDataArray
 */
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
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







-
+

-
+





-
+



-
+







- (void)insertItem: (const void*)item
	   atIndex: (size_t)index;

/*!
 * @brief Adds items from a C array to the OFDataArray.
 *
 * @param count The number of items to add
 * @param cArray A C array containing the items to add
 * @param items A C array containing the items to add
 */
- (void)addItemsFromCArray: (const void*)cArray
- (void)addItems: (const void*)array
		     count: (size_t)count;

/*!
 * @brief Adds items from a C array to the OFDataArray at the specified index.
 *
 * @param cArray A C array containing the items to add
 * @param items A C array containing the items to add
 * @param index The index where the items should be added
 * @param count The number of items to add
 */
- (void)insertItemsFromCArray: (const void*)cArray
- (void)insertItems: (const void*)items
		      atIndex: (size_t)index
			count: (size_t)count;

/*!
 * @brief Removes the item at the specified index.
 *
 * @param index The index of the item to remove

Modified src/OFDataArray.m from [ca2bfba7fb] to [9afe18d8f2].

116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130







-
+







			char *buffer = [self allocMemoryWithSize: of_pagesize];

			while (![file isAtEndOfStream]) {
				size_t length;

				length = [file readIntoBuffer: buffer
						       length: of_pagesize];
				[self addItemsFromCArray: buffer
				[self addItems: buffer
						   count: length];
			}

			[self freeMemory: buffer];
		} @finally {
			[file release];
		}
183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197







-
+








		if (count & 1)
			@throw [OFInvalidFormatException
			    exceptionWithClass: [self class]];

		count >>= 1;
		cString = [string UTF8String];
		data = [self allocMemoryWithSize: count];
		items = [self allocMemoryWithSize: count];

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

			if (c1 >= '0' && c1 <= '9')
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224







-
+







				byte |= c2 - 'a' + 10;
			else if (c2 >= 'A' && c2 <= 'F')
				byte |= c2 - 'A' + 10;
			else
				@throw [OFInvalidFormatException
				    exceptionWithClass: [self class]];

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

	return self;
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
358

359
360

361
362

363
364
365

366
367

368
369

370
371

372
373

374
375
376
377
378
379
380
381
382
383
384
385
386
387
388


389
390
391
392
393

394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
418

419
420

421
422
423
424
425
426
427
428

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

447
448
449
450
451
452
453
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

358
359

360
361

362
363
364

365
366

367
368

369
370

371
372

373
374
375
376
377
378
379
380
381
382
383
384
385
386


387
388
389
390
391
392

393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
415
416
417

418
419

420
421
422
423
424
425
426
427

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

446
447
448
449
450
451
452
453







-
+

-
+







-
+




-
+


-
+




-
+


-
+







-
+



-
+







-
+




-
-
+
+

-
+


-
+

-
+

-
-
+
+


-
+

-
+

-
+


-
+

-
+

-
+

-
+

-
+













-
-
+
+




-
+














-
+









-
+

-
+







-
+

















-
+







}

- (size_t)itemSize
{
	return itemSize;
}

- (void*)cArray
- (void*)items
{
	return data;
	return items;
}

- (void*)itemAtIndex: (size_t)index
{
	if (index >= count)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	return data + index * itemSize;
	return items + index * itemSize;
}

- (void*)firstItem
{
	if (data == NULL || count == 0)
	if (items == NULL || count == 0)
		return NULL;

	return data;
	return items;
}

- (void*)lastItem
{
	if (data == NULL || count == 0)
	if (items == NULL || count == 0)
		return NULL;

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

- (void)addItem: (const void*)item
{
	if (SIZE_MAX - count < 1)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	data = [self resizeMemory: data
	items = [self resizeMemory: items
			     size: itemSize
			    count: count + 1];

	memcpy(data + count * itemSize, item, itemSize);
	memcpy(items + count * itemSize, item, itemSize);

	count++;
}

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

- (void)addItemsFromCArray: (const void*)cArray
		     count: (size_t)nItems
- (void)addItems: (const void*)items_
	   count: (size_t)count_
{
	if (nItems > SIZE_MAX - count)
	if (count_ > SIZE_MAX - count)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	data = [self resizeMemory: data
	items = [self resizeMemory: items
			     size: itemSize
			    count: count + nItems];
			     count: count + count_];

	memcpy(data + count * itemSize, cArray, nItems * itemSize);
	count += nItems;
	memcpy(items + count * itemSize, items_, count_ * itemSize);
	count += count_;
}

- (void)insertItemsFromCArray: (const void*)cArray
- (void)insertItems: (const void*)items_
		      atIndex: (size_t)index
			count: (size_t)nItems
	      count: (size_t)count_
{
	if (nItems > SIZE_MAX - count || index > count)
	if (count_ > SIZE_MAX - count || index > count)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	data = [self resizeMemory: data
	items = [self resizeMemory: items
			     size: itemSize
			    count: count + nItems];
			     count: count + count_];

	memmove(data + (index + nItems) * itemSize, data + index * itemSize,
	memmove(items + (index + count_) * itemSize, items + index * itemSize,
	    (count - index) * itemSize);
	memcpy(data + index * itemSize, cArray, nItems * itemSize);
	memcpy(items + index * itemSize, items_, count_ * itemSize);

	count += nItems;
	count += count_;
}

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

- (void)removeItemsInRange: (of_range_t)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > count)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	memmove(data + range.location * itemSize,
	    data + (range.location + range.length) * itemSize,
	memmove(items + range.location * itemSize,
	    items + (range.location + range.length) * itemSize,
	    (count - range.location - range.length) * itemSize);

	count -= range.length;
	@try {
		data = [self resizeMemory: data
		items = [self resizeMemory: items
				     size: itemSize
				    count: count];
	} @catch (OFOutOfMemoryException *e) {
		/* We don't really care, as we only made it smaller */
	}
}

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

	count--;
	@try {
		data = [self resizeMemory: data
		items = [self resizeMemory: items
				     size: itemSize
				    count: count];
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only made it smaller */
	}
}

- (void)removeAllItems
{
	[self freeMemory: data];
	[self freeMemory: items];

	data = NULL;
	items = NULL;
	count = 0;
}

- copy
{
	OFDataArray *copy = [[[self class] alloc] initWithItemSize: itemSize];

	[copy addItemsFromCArray: data
	[copy addItems: items
			   count: count];

	return copy;
}

- (BOOL)isEqual: (id)object
{
	OFDataArray *otherDataArray;

	if (![object isKindOfClass: [OFDataArray class]])
		return NO;

	otherDataArray = object;

	if ([otherDataArray count] != count ||
	    [otherDataArray itemSize] != itemSize)
		return NO;
	if (memcmp([otherDataArray cArray], data, count * itemSize))
	if (memcmp([otherDataArray items], items, count * itemSize))
		return NO;

	return YES;
}

- (of_comparison_result_t)compare: (id <OFComparing>)object
{
465
466
467
468
469
470
471
472

473
474
475
476
477
478
479
465
466
467
468
469
470
471

472
473
474
475
476
477
478
479







-
+







		@throw [OFInvalidArgumentException
		    exceptionWithClass: [self class]
			      selector: _cmd];

	otherCount = [otherDataArray count];
	minimumCount = (count > otherCount ? otherCount : count);

	if ((comparison = memcmp(data, [otherDataArray cArray],
	if ((comparison = memcmp(items, [otherDataArray items],
	    minimumCount * itemSize)) == 0) {
		if (count > otherCount)
			return OF_ORDERED_DESCENDING;
		if (count < otherCount)
			return OF_ORDERED_ASCENDING;
		return OF_ORDERED_SAME;
	}
488
489
490
491
492
493
494
495

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

515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536
537
538

539
540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568

569
570
571
572
573
574
575
488
489
490
491
492
493
494

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

514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
575







-
+


















-
+















-
+







-
+








-
+




















-
+







{
	uint32_t hash;
	size_t i;

	OF_HASH_INIT(hash);

	for (i = 0; i < count * itemSize; i++)
		OF_HASH_ADD(hash, ((char*)data)[i]);
		OF_HASH_ADD(hash, ((uint8_t*)items)[i]);

	OF_HASH_FINALIZE(hash);

	return hash;
}

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

	for (i = 0; i < count; i++) {
		size_t j;

		if (i > 0)
			[ret appendString: @" "];

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

	[ret appendString: @">"];

	[ret makeImmutable];
	return ret;
}

- (OFString*)stringRepresentation
{
	OFMutableString *ret = [OFMutableString string];
	size_t i, j;

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

	[ret makeImmutable];
	return ret;
}

- (OFString*)stringByBase64Encoding
{
	return of_base64_encode(data, count * itemSize);
	return of_base64_encode(items, count * itemSize);
}

- (void)writeToFile: (OFString*)path
{
	OFFile *file = [[OFFile alloc] initWithPath: path
					       mode: @"wb"];

	@try {
		[file writeBuffer: data
		[file writeBuffer: items
			   length: count * itemSize];
	} @finally {
		[file release];
	}
}

- (OFXMLElement*)XMLElementBySerializing
{
	void *pool;
	OFXMLElement *element;

	if (itemSize != 1)
		@throw [OFNotImplementedException
		    exceptionWithClass: [self class]
			      selector: _cmd];

	pool = objc_autoreleasePoolPush();
	element = [OFXMLElement
	    elementWithName: [self className]
		  namespace: OF_SERIALIZATION_NS
		stringValue: of_base64_encode(data, count * itemSize)];
		stringValue: of_base64_encode(items, count * itemSize)];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}
583
584
585
586
587
588
589
590

591
592
593

594
595
596
597
598
599
600


601
602
603
604

605
606
607
608

609
610
611

612
613
614

615
616

617
618
619
620

621
622

623
624
625
626
627


628
629
630
631

632
633
634

635
636
637

638
639

640
641

642
643
644
645
646
647
648
649
650
651
652
653
654


655
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680

681
682
683
684
685
686
687
688
689
690
691
692

693
694

695
696
697
698
583
584
585
586
587
588
589

590
591
592

593
594
595
596
597
598


599
600
601
602
603

604
605
606
607

608
609
610

611
612
613

614
615

616
617
618
619

620
621

622
623
624
625


626
627
628
629
630

631
632
633

634
635
636

637
638

639
640

641
642
643
644
645
646
647
648
649
650
651
652


653
654
655
656
657
658
659
660
661

662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679

680
681
682
683
684
685
686
687
688
689
690
691

692
693

694
695
696
697
698







-
+


-
+





-
-
+
+



-
+



-
+


-
+


-
+

-
+



-
+

-
+



-
-
+
+



-
+


-
+


-
+

-
+

-
+











-
-
+
+







-
+

















-
+











-
+

-
+




	if (SIZE_MAX - count < 1 || count + 1 > SIZE_MAX / itemSize)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	lastPageByte = of_pagesize - 1;
	newSize = ((count + 1) * itemSize + lastPageByte) & ~lastPageByte;

	if (size != newSize)
		data = [self resizeMemory: data
		items = [self resizeMemory: items
				     size: newSize];

	memcpy(data + count * itemSize, item, itemSize);
	memcpy(items + count * itemSize, item, itemSize);

	count++;
	size = newSize;
}

- (void)addItemsFromCArray: (const void*)cArray
		     count: (size_t)nItems
- (void)addItems: (const void*)items_
	   count: (size_t)count_
{
	size_t newSize, lastPageByte;

	if (nItems > SIZE_MAX - count || count + nItems > SIZE_MAX / itemSize)
	if (count_ > SIZE_MAX - count || count + count_ > SIZE_MAX / itemSize)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	lastPageByte = of_pagesize - 1;
	newSize = ((count + nItems) * itemSize + lastPageByte) & ~lastPageByte;
	newSize = ((count + count_) * itemSize + lastPageByte) & ~lastPageByte;

	if (size != newSize)
		data = [self resizeMemory: data
		items = [self resizeMemory: items
				     size: newSize];

	memcpy(data + count * itemSize, cArray, nItems * itemSize);
	memcpy(items + count * itemSize, items_, count_ * itemSize);

	count += nItems;
	count += count_;
	size = newSize;
}

- (void)insertItemsFromCArray: (const void*)cArray
- (void)insertItems: (const void*)items_
		      atIndex: (size_t)index
			count: (size_t)nItems
	      count: (size_t)count_
{
	size_t newSize, lastPageByte;

	if (nItems > SIZE_MAX - count || index > count ||
	    count + nItems > SIZE_MAX / itemSize)
	if (count_ > SIZE_MAX - count || index > count ||
	    count + count_ > SIZE_MAX / itemSize)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	lastPageByte = of_pagesize - 1;
	newSize = ((count + nItems) * itemSize + lastPageByte) & ~lastPageByte;
	newSize = ((count + count_) * itemSize + lastPageByte) & ~lastPageByte;

	if (size != newSize)
		data = [self resizeMemory: data
		items = [self resizeMemory: items
				     size: newSize];

	memmove(data + (index + nItems) * itemSize, data + index * itemSize,
	memmove(items + (index + count_) * itemSize, items + index * itemSize,
	    (count - index) * itemSize);
	memcpy(data + index * itemSize, cArray, nItems * itemSize);
	memcpy(items + index * itemSize, items_, count_ * itemSize);

	count += nItems;
	count += count_;
	size = newSize;
}

- (void)removeItemsInRange: (of_range_t)range
{
	size_t newSize, lastPageByte;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > count)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	memmove(data + range.location * itemSize,
	    data + (range.location + range.length) * itemSize,
	memmove(items + range.location * itemSize,
	    items + (range.location + range.length) * itemSize,
	    (count - range.location - range.length) * itemSize);

	count -= range.length;
	lastPageByte = of_pagesize - 1;
	newSize = (count * itemSize + lastPageByte) & ~lastPageByte;

	if (size != newSize)
		data = [self resizeMemory: data
		items = [self resizeMemory: items
				     size: newSize];
	size = newSize;
}

- (void)removeLastItem
{
	size_t newSize, lastPageByte;

	if (count == 0)
		return;

	count--;
	lastPageByte = of_pagesize - 1;
	newSize = (count * itemSize + lastPageByte) & ~lastPageByte;

	if (size != newSize) {
		@try {
			data = [self resizeMemory: data
			items = [self resizeMemory: items
					     size: newSize];
		} @catch (OFOutOfMemoryException *e) {
			/* We don't care, as we only made it smaller */
		}

		size = newSize;
	}
}

- (void)removeAllItems
{
	[self freeMemory: data];
	[self freeMemory: items];

	data = NULL;
	items = NULL;
	count = 0;
	size = 0;
}
@end

Modified src/OFHTTPClient.m from [befaf122bc] to [9d0e6d26b7].

215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229







-
+







	[sock writeString: @"\r\n"];

	/* Work around a bug in lighttpd, see above */
	[sock flushWriteBuffer];
	[sock setWriteBufferEnabled: NO];

	if (requestType == OF_HTTP_REQUEST_TYPE_POST)
		[sock writeBuffer: [POSTData cArray]
		[sock writeBuffer: [POSTData items]
			   length: [POSTData count] * [POSTData itemSize]];

	@try {
		line = [sock readLine];
	} @catch (OFInvalidEncodingException *e) {
		@throw [OFInvalidServerReplyException
		    exceptionWithClass: [self class]];
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
403
404
405
406
407
408
409

410
411
412
413
414
415
416
417







-
+







						  length: length
						 request: request];

					objc_autoreleasePoolPop(pool2);
					pool2 = objc_autoreleasePoolPush();

					bytesReceived += length;
					[data addItemsFromCArray: buffer
					[data addItems: buffer
							   count: length];

					toRead -= length;
				}

				@try {
					line = [sock readLine];
441
442
443
444
445
446
447
448

449
450
451
452
453
454
455
441
442
443
444
445
446
447

448
449
450
451
452
453
454
455







-
+







				  didReceiveData: buffer
					  length: length
					 request: request];

				objc_autoreleasePoolPop(pool2);

				bytesReceived += length;
				[data addItemsFromCArray: buffer
				[data addItems: buffer
						   count: length];

				if (contentLengthHeader != nil &&
				    bytesReceived >= contentLength)
					break;
			}
		}

Modified src/OFHTTPServer.m from [e6f92f7b1d] to [61524a3f46].

396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
396
397
398
399
400
401
402

403
404
405
406
407
408
409
410







-
+







  didReadIntoBuffer: (const char*)buffer
	     length: (size_t)length
	  exception: (OFException*)exception
{
	if ([sock_ isAtEndOfStream] || exception != nil)
		return NO;

	[POSTData addItemsFromCArray: buffer
	[POSTData addItems: buffer
			       count: length];

	if ([POSTData count] >= contentLength) {
		@try {
			[self sendReply];
		} @catch (OFWriteFailedException *e) {
			return NO;
497
498
499
500
501
502
503
504

505
506
507
508
509
510
511
497
498
499
500
501
502
503

504
505
506
507
508
509
510
511







-
+







	while ((key = [keyEnumerator nextObject]) != nil &&
	    (value = [valueEnumerator nextObject]) != nil)
		[sock writeFormat: @"%@: %@\r\n", key, value];

	[sock writeString: @"\r\n"];

	if (requestType != OF_HTTP_REQUEST_TYPE_HEAD)
		[sock writeBuffer: [replyData cArray]
		[sock writeBuffer: [replyData items]
			   length: [replyData count] * [replyData itemSize]];
}
@end

@implementation OFHTTPServer
+ (instancetype)server
{

Modified src/OFMD5Hash.h from [b8a9b23fd3] to [569dd9f1c4].

whitespace changes only

Modified src/OFMutableArray_adjacent.m from [b75900fe79] to [f345fceab0].

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







-
+



















-
+








- (void)insertObjectsFromArray: (OFArray*)array_
		       atIndex: (size_t)index
{
	id *objects = [array_ objects];
	size_t i, count = [array_ count];

	[array insertItemsFromCArray: objects
	[array insertItems: objects
			     atIndex: index
			       count: count];

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

	mutations++;
}

- (void)replaceObject: (id)oldObject
	   withObject: (id)newObject
{
	id *objects;
	size_t i, count;

	if (oldObject == nil || newObject == nil)
		@throw [OFInvalidArgumentException
		    exceptionWithClass: [self class]];

	objects = [array cArray];
	objects = [array items];
	count = [array count];

	for (i = 0; i < count; i++) {
		if ([objects[i] isEqual: oldObject]) {
			[newObject retain];
			[objects[i] release];
			objects[i] = newObject;
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
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







-
+



















-
+







	id *objects;
	id oldObject;

	if (object == nil)
		@throw [OFInvalidArgumentException
		    exceptionWithClass: [self class]];

	objects = [array cArray];
	objects = [array items];

	if (index >= [array count])
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

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

- (void)replaceObjectIdenticalTo: (id)oldObject
		      withObject: (id)newObject
{
	id *objects;
	size_t i, count;

	if (oldObject == nil || newObject == nil)
		@throw [OFInvalidArgumentException
		    exceptionWithClass: [self class]];

	objects = [array cArray];
	objects = [array items];
	count = [array count];

	for (i = 0; i < count; i++) {
		if (objects[i] == oldObject) {
			[newObject retain];
			[objects[i] release];
			objects[i] = newObject;
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162







-
+







	id *objects;
	size_t i, count;

	if (object == nil)
		@throw [OFInvalidArgumentException
		    exceptionWithClass: [self class]];

	objects = [array cArray];
	objects = [array items];
	count = [array count];

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

			[array removeItemAtIndex: i];
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188







-
+







	id *objects;
	size_t i, count;

	if (object == nil)
		@throw [OFInvalidArgumentException
		    exceptionWithClass: [self class]];

	objects = [array cArray];
	objects = [array items];
	count = [array count];

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

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







-
+










-
+







	[object release];

	mutations++;
}

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

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

	[array removeAllItems];
}

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

	if (range.length > SIZE_MAX - range.location ||
	    range.length > count - range.location)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	copy = [self allocMemoryWithSize: sizeof(*copy)
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
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







-
+













-
+








	mutations++;
}

- (void)exchangeObjectAtIndex: (size_t)index1
	    withObjectAtIndex: (size_t)index2
{
	id *objects = [array cArray];
	id *objects = [array items];
	size_t count = [array count];
	id tmp;

	if (index1 >= count || index2 >= count)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	tmp = objects[index1];
	objects[index1] = objects[index2];
	objects[index2] = tmp;
}

- (void)reverse
{
	id *objects = [array cArray];
	id *objects = [array items];
	size_t i, j, count = [array count];

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

	for (i = 0, j = count - 1; i < j; i++, j--) {
		id tmp = objects[i];
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
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







-
+
















-
+







	    initWithArray: self
	     mutationsPtr: &mutations] autorelease];
}

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

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

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

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

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

Modified src/OFStream.m from [cea01024de] to [c1d9e7762b].

496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
496
497
498
499
500
501
502

503
504
505
506
507
508
509
510







-
+







	tmp = [self allocMemoryWithSize: itemSize
				  count: count];

	@try {
		[self readIntoBuffer: tmp
			 exactLength: count * itemSize];

		[dataArray addItemsFromCArray: tmp
		[dataArray addItems: tmp
					count: count];
	} @finally {
		[self freeMemory: tmp];
	}

	return dataArray;
}
519
520
521
522
523
524
525
526

527
528
529
530
531
532
533
519
520
521
522
523
524
525

526
527
528
529
530
531
532
533







-
+








	@try {
		while (![self isAtEndOfStream]) {
			size_t length;

			length = [self readIntoBuffer: buffer
					       length: of_pagesize];
			[dataArray addItemsFromCArray: buffer
			[dataArray addItems: buffer
						count: length];
		}
	} @finally {
		[self freeMemory: buffer];
	}

	return dataArray;
1353
1354
1355
1356
1357
1358
1359
1360

1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1353
1354
1355
1356
1357
1358
1359

1360
1361
1362

1363
1364
1365
1366
1367
1368
1369
1370







-
+


-
+







	return size;
}

- (size_t)writeDataArray: (OFDataArray*)dataArray
{
	size_t length = [dataArray count] * [dataArray itemSize];

	[self writeBuffer: [dataArray cArray]
	[self writeBuffer: [dataArray items]
		   length: length];

	return [dataArray count] * [dataArray itemSize];
	return length;
}

- (size_t)writeString: (OFString*)string
{
	size_t length = [string UTF8StringLength];

	[self writeBuffer: [string UTF8String]

Modified src/OFStreamObserver.m from [f18e106529] to [0c778cd456].

289
290
291
292
293
294
295
296
297


298
299
300
301
302
303


304
305
306
307
308
309
310
289
290
291
292
293
294
295


296
297
298
299
300
301


302
303
304
305
306
307
308
309
310







-
-
+
+




-
-
+
+







}

- (void)OF_processQueue
{
	[mutex lock];
	@try {
		OFStream **queueObjects = [queue objects];
		int *queueInfoCArray = [queueInfo cArray];
		int *queueFDsCArray = [queueFDs cArray];
		int *queueInfoItems = [queueInfo items];
		int *queueFDsItems = [queueFDs items];
		size_t i, count = [queue count];

		for (i = 0; i < count; i++) {
			OFStream *stream = queueObjects[i];
			int action = queueInfoCArray[i];
			int fd = queueFDsCArray[i];
			int action = queueInfoItems[i];
			int fd = queueFDsItems[i];

			if ((action & QUEUE_ACTION) == QUEUE_ADD) {
				if (fd > maxFD) {
					maxFD = fd;
					FDToStream = [self
					    resizeMemory: FDToStream
						    size: sizeof(OFStream*)

Modified src/OFStreamObserver_kqueue.m from [1e1bf29b71] to [c9bbb01ae1].

120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134







-
+







	if ([self OF_processCache]) {
		objc_autoreleasePoolPop(pool);
		return YES;
	}

	objc_autoreleasePoolPop(pool);

	events = kevent(kernelQueue, [changeList cArray],
	events = kevent(kernelQueue, [changeList items],
	    (int)[changeList count], eventList, EVENTLIST_SIZE,
	    (timeout == -1 ? NULL : &timespec));

	if (events == -1) {
		switch (errno) {
		case EINTR:
			return NO;

Modified src/OFStreamObserver_poll.m from [ca9d956364] to [c07acfe92a].

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







-
+




-
-
+
+














-
+



-
-
+
+

-
+








	[super dealloc];
}

- (void)OF_addFileDescriptor: (int)fd
		  withEvents: (short)events
{
	struct pollfd *FDsCArray = [FDs cArray];
	struct pollfd *FDs_ = [FDs items];
	size_t i, count = [FDs count];
	BOOL found = NO;

	for (i = 0; i < count; i++) {
		if (FDsCArray[i].fd == fd) {
			FDsCArray[i].events |= events;
		if (FDs_[i].fd == fd) {
			FDs_[i].events |= events;
			found = YES;
			break;
		}
	}

	if (!found) {
		struct pollfd p = { fd, events | POLLERR, 0 };
		[FDs addItem: &p];
	}
}

- (void)OF_removeFileDescriptor: (int)fd
		     withEvents: (short)events
{
	struct pollfd *FDsCArray = [FDs cArray];
	struct pollfd *FDs_ = [FDs items];
	size_t i, nFDs = [FDs count];

	for (i = 0; i < nFDs; i++) {
		if (FDsCArray[i].fd == fd) {
			FDsCArray[i].events &= ~events;
		if (FDs_[i].fd == fd) {
			FDs_[i].events &= ~events;

			if ((FDsCArray[i].events & ~POLLERR) == 0)
			if ((FDs_[i].events & ~POLLERR) == 0)
				[FDs removeItemAtIndex: i];

			break;
		}
	}
}

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







-
+











-
+







-
+






-
-
+
+



-
+







-
+


-
+


-
+


-
+


-
+


-
+










	[self OF_removeFileDescriptor: fd
			   withEvents: POLLOUT];
}

- (BOOL)observeWithTimeout: (double)timeout
{
	void *pool = objc_autoreleasePoolPush();
	struct pollfd *FDsCArray;
	struct pollfd *FDs_;
	size_t i, nFDs, realEvents = 0;

	[self OF_processQueue];

	if ([self OF_processCache]) {
		objc_autoreleasePoolPop(pool);
		return YES;
	}

	objc_autoreleasePoolPop(pool);

	FDsCArray = [FDs cArray];
	FDs_ = [FDs items];
	nFDs = [FDs count];

#ifdef OPEN_MAX
	if (nFDs > OPEN_MAX)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];
#endif

	if (poll(FDsCArray, (nfds_t)nFDs,
	if (poll(FDs_, (nfds_t)nFDs,
	    (int)(timeout != -1 ? timeout * 1000 : -1)) < 1)
		return NO;

	for (i = 0; i < nFDs; i++) {
		pool = objc_autoreleasePoolPush();

		if (FDsCArray[i].revents & POLLIN) {
			if (FDsCArray[i].fd == cancelFD[0]) {
		if (FDs_[i].revents & POLLIN) {
			if (FDs_[i].fd == cancelFD[0]) {
				char buffer;

				OF_ENSURE(read(cancelFD[0], &buffer, 1) > 0);
				FDsCArray[i].revents = 0;
				FDs_[i].revents = 0;

				objc_autoreleasePoolPop(pool);
				continue;
			}

			realEvents++;
			[delegate streamIsReadyForReading:
			    FDToStream[FDsCArray[i].fd]];
			    FDToStream[FDs_[i].fd]];
		}

		if (FDsCArray[i].revents & POLLOUT) {
		if (FDs_[i].revents & POLLOUT) {
			realEvents++;
			[delegate streamIsReadyForWriting:
			    FDToStream[FDsCArray[i].fd]];
			    FDToStream[FDs_[i].fd]];
		}

		if (FDsCArray[i].revents & POLLERR) {
		if (FDs_[i].revents & POLLERR) {
			realEvents++;
			[delegate streamDidReceiveException:
			    FDToStream[FDsCArray[i].fd]];
			    FDToStream[FDs_[i].fd]];
		}

		FDsCArray[i].revents = 0;
		FDs_[i].revents = 0;

		objc_autoreleasePoolPop(pool);
	}

	if (realEvents == 0)
		return NO;

	return YES;
}
@end

Modified src/OFString.m from [90ef2353c5] to [712053e8f6].

779
780
781
782
783
784
785
786

787
788
789
790
791
792
793
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793







-
+







		if ([contentType hasSuffix: @"charset=windows-1252"])
			encoding = OF_STRING_ENCODING_WINDOWS_1252;
	}

	if (encoding == OF_STRING_ENCODING_AUTODETECT)
		encoding = OF_STRING_ENCODING_UTF_8;

	self = [[c alloc] initWithCString: (char*)[[result data] cArray]
	self = [[c alloc] initWithCString: (char*)[[result data] items]
				 encoding: encoding
				   length: [[result data] count]];

	objc_autoreleasePoolPop(pool);
	return self;
}

Modified src/OFXMLElement.m from [177c46b1d0] to [16ca049b3f].

636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662

663
664
665
666
667
668
669
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

662
663
664
665
666
667
668
669







-
+


















-
+







					       indentation: ind
						     level: level + 1];
			else
				child = [childrenObjects[j]
				    XMLStringWithIndentation: ind
						       level: level + 1];

			[tmp addItemsFromCArray: [child UTF8String]
			[tmp addItems: [child UTF8String]
					  count: [child UTF8StringLength]];
		}

		if (indent)
			[tmp addItem: "\n"];

		length += [tmp count] + [name UTF8StringLength] + 2 +
		    (indent ? level * indentation : 0);
		@try {
			cString = [self resizeMemory: cString
						size: length];
		} @catch (id e) {
			[self freeMemory: cString];
			@throw e;
		}

		cString[i++] = '>';

		memcpy(cString + i, [tmp cArray], [tmp count]);
		memcpy(cString + i, [tmp items], [tmp count]);
		i += [tmp count];

		if (indent) {
			memset(cString + i, ' ', level * indentation);
			i += level * indentation;
		}

Modified src/OFXMLParser.m from [c33143cf90] to [4543342dd4].

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







-
+






-
+









-
+




-
+



-
-
+
+

-
+




-
-
+
+



-
+







static state_function lookupTable[OF_XMLPARSER_NUM_STATES];

static OF_INLINE void
cache_append(OFDataArray *cache, const char *string,
    of_string_encoding_t encoding, size_t length)
{
	if (OF_LIKELY(encoding == OF_STRING_ENCODING_UTF_8))
		[cache addItemsFromCArray: string
		[cache addItems: string
				    count: length];
	else {
		void *pool = objc_autoreleasePoolPush();
		OFString *tmp = [OFString stringWithCString: string
						   encoding: encoding
						     length: length];
		[cache addItemsFromCArray: [tmp UTF8String]
		[cache addItems: [tmp UTF8String]
				    count: [tmp UTF8StringLength]];
		objc_autoreleasePoolPop(pool);
	}
}

static OFString*
transform_string(OFDataArray *cache, size_t cut, BOOL unescape,
    id <OFStringXMLUnescapingDelegate> delegate)
{
	char *cArray;
	char *items;
	size_t i, length;
	BOOL hasEntities = NO;
	OFMutableString *ret;

	cArray = [cache cArray];
	items = [cache items];
	length = [cache count] - cut;

	for (i = 0; i < length; i++) {
		if (cArray[i] == '\r') {
			if (i + 1 < length && cArray[i + 1] == '\n') {
		if (items[i] == '\r') {
			if (i + 1 < length && items[i + 1] == '\n') {
				[cache removeItemAtIndex: i];
				cArray = [cache cArray];
				items = [cache items];

				i--;
				length--;
			} else
				cArray[i] = '\n';
		} else if (cArray[i] == '&')
				items[i] = '\n';
		} else if (items[i] == '&')
			hasEntities = YES;
	}

	ret = [OFMutableString stringWithUTF8String: cArray
	ret = [OFMutableString stringWithUTF8String: items
					     length: length];

	if (unescape && hasEntities)
		return [ret stringByXMLUnescapingWithDelegate: delegate];

	[ret makeImmutable];

533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
533
534
535
536
537
538
539

540
541
542
543
544
545
546
547







-
+







		return;

	if ((length = *i - *last) > 0)
		cache_append(cache, buffer + *last, encoding, length);

	pool = objc_autoreleasePoolPush();

	cacheCString = [cache cArray];
	cacheCString = [cache items];
	cacheLength = [cache count];
	cacheString = [OFString stringWithUTF8String: cacheCString
					      length: cacheLength];

	if ((tmp = memchr(cacheCString, ':', cacheLength)) != NULL) {
		name = [[OFString alloc]
		    initWithUTF8String: tmp + 1
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
+







		return;

	if ((length = *i - *last) > 0)
		cache_append(cache, buffer + *last, encoding, length);

	pool = objc_autoreleasePoolPush();

	cacheCString = [cache cArray];
	cacheCString = [cache items];
	cacheLength = [cache count];
	cacheString = [OFString stringWithUTF8String: cacheCString
					      length: cacheLength];

	if ((tmp = memchr(cacheCString, ':', cacheLength)) != NULL) {
		name = [[OFString alloc]
		    initWithUTF8String: tmp + 1
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773







-
+







		return;

	if ((length = *i - *last) > 0)
		cache_append(cache, buffer + *last, encoding, length);

	pool = objc_autoreleasePoolPush();

	cacheString = [OFMutableString stringWithUTF8String: [cache cArray]
	cacheString = [OFMutableString stringWithUTF8String: [cache items]
						     length: [cache count]];
	[cacheString deleteEnclosingWhitespaces];
	/* Prevent a useless copy later */
	[cacheString makeImmutable];

	cacheCString = [cacheString UTF8String];
	cacheLength = [cacheString UTF8StringLength];

Modified src/base64.m from [9c1fb17538] to [c2598ccd38].

146
147
148
149
150
151
152
153

154
155
156
157
158
146
147
148
149
150
151
152

153
154
155
156
157
158







-
+






		sb |= tmp;

		db[0] = (sb & 0xFF0000) >> 16;
		db[1] = (sb & 0x00FF00) >> 8;
		db[2] = sb & 0x0000FF;

		[data addItemsFromCArray: db
		[data addItems: db
				   count: count];
	}

	return YES;
}

Modified tests/OFDataArrayTests.m from [eae28a70a3] to [6c7d01470b].

57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71







-
+








	TEST(@"-[count]", [array[0] count] == 2)

	other = (class == [OFDataArray class]
	    ? [OFBigDataArray class]
	    : [OFDataArray class]);
	TEST(@"-[isEqual:]", (array[1] = [other dataArrayWithItemSize: 4096]) &&
	    R([array[1] addItemsFromCArray: [array[0] cArray]
	    R([array[1] addItems: [array[0] items]
				     count: [array[0] count]]) &&
	    [array[1] isEqual: array[0]] &&
	    R([array[1] removeLastItem]) && ![array[0] isEqual: array[1]])

	TEST(@"-[copy]", (array[1] = [[array[0] copy] autorelease]) &&
	    [array[0] isEqual: array[1]])

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







-
+




-
+



-
+

-
-
+
+


-
+










-
+



-
+

-
+




-
+
-
-
+







	    [array[0] compare: array[1]] == OF_ORDERED_DESCENDING &&
	    [array[1] compare: array[0]] == OF_ORDERED_ASCENDING &&
	    [array[2] compare: array[3]] == OF_ORDERED_ASCENDING)

	TEST(@"-[hash]", [array[0] hash] == 0x634A529F)

	array[0] = [class dataArray];
	[array[0] addItemsFromCArray: "abcdef"
	[array[0] addItems: "abcdef"
			       count: 6];

	TEST(@"-[removeLastItem]", R([array[0] removeLastItem]) &&
	    [array[0] count] == 5 &&
	    !memcmp([array[0] cArray], "abcde", 5))
	    !memcmp([array[0] items], "abcde", 5))

	TEST(@"-[removeItemsInRange:]",
	    R([array[0] removeItemsInRange: of_range(1, 2)]) &&
	    [array[0] count] == 3 && !memcmp([array[0] cArray], "ade", 3))
	    [array[0] count] == 3 && !memcmp([array[0] items], "ade", 3))

	TEST(@"-[insertItemsFromCArray:atIndex:count:]",
	    R([array[0] insertItemsFromCArray: "bc"
	TEST(@"-[insertItems:atIndex:count:]",
	    R([array[0] insertItems: "bc"
				      atIndex: 1
					count: 2]) && [array[0] count] == 5 &&
	    !memcmp([array[0] cArray], "abcde", 5))
	    !memcmp([array[0] items], "abcde", 5))

	TEST(@"-[MD5Hash]", [[array[0] MD5Hash] isEqual: [@"abcde" MD5Hash]])

	TEST(@"-[SHA1Hash]", [[array[0] SHA1Hash] isEqual: [@"abcde" SHA1Hash]])

	TEST(@"-[stringByBase64Encoding]",
	    [[array[0] stringByBase64Encoding] isEqual: @"YWJjZGU="])

	TEST(@"+[dataArrayWithBase64EncodedString:]",
	    !memcmp([[class dataArrayWithBase64EncodedString: @"YWJjZGU="]
	    cArray], "abcde", 5))
	    items], "abcde", 5))

	TEST(@"Building strings",
	    (array[0] = [class dataArray]) &&
	    R([array[0] addItemsFromCArray: (void*)str
	    R([array[0] addItems: (void*)str
				     count: 6]) && R([array[0] addItem: ""]) &&
	    !strcmp([array[0] cArray], str))
	    !strcmp([array[0] items], str))

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

	EXPECT_EXCEPTION(@"Detect out of range in "
	EXPECT_EXCEPTION(@"Detect out of range in -[addItems:count:]",
	    @"-[addItemsFromCArray:count:]",
	    OFOutOfRangeException, [array[0] addItemsFromCArray: NULL
	    OFOutOfRangeException, [array[0] addItems: NULL
							  count: SIZE_MAX])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeItemsInRange:]",
	    OFOutOfRangeException,
	    [array[0] removeItemsInRange: of_range([array[0] count], 1)])
}

Modified tests/OFSerializationTests.m from [cf7d67e102] to [61f9a15e64].

63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77







-
+







	[l appendObject: [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]];
	[l appendObject:
	    [OFCountedSet setWithObjects: @"foo", @"foo", @"bar", nil]];

	[d setObject: @"list"
	      forKey: l];

	[da addItemsFromCArray: "0123456789:;<ABCDEFGHJIKLMNOPQRSTUVWXYZ"
	[da addItems: "0123456789:;<ABCDEFGHJIKLMNOPQRSTUVWXYZ"
			 count: 39];
	[d setObject: @"data"
	      forKey: da];

	TEST(@"-[stringBySerializing]",
	    (s = [d stringBySerializing]) && [s isEqual:
	    [OFString stringWithContentsOfFile: @"serialization.xml"]])