ObjFW  Check-in [c9433ea60d]

Overview
Comment:range.start -> range.location.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: c9433ea60d2581ef6b48b22d9dd61f22eea24baf98a73236b56f0a97bf5bcd57
User & Date: js on 2012-10-14 00:54:58
Other Links: manifest | tags
Context
2012-10-14
00:59
OF_INVALID_INDEX -> OF_NOT_FOUND. check-in: f38744df74 user: js tags: trunk
00:54
range.start -> range.location. check-in: c9433ea60d user: js tags: trunk
2012-10-13
22:21
Add -[OFString rangeOfString:options:range:]. check-in: 20dddc7345 user: js tags: trunk
Changes

Modified src/OFArray.m from [65f72110ac] to [462ac6c7f4].

231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245







-
+








- (void)getObjects: (id*)buffer
	   inRange: (of_range_t)range
{
	size_t i;

	for (i = 0; i < range.length; i++)
		buffer[i] = [self objectAtIndex: range.start + i];
		buffer[i] = [self objectAtIndex: range.location + i];
}

- (id*)objects
{
	OFObject *container;
	size_t count;
	id *buffer;

Modified src/OFArray_adjacent.m from [9a07b7851a] to [96ab47295a].

208
209
210
211
212
213
214
215

216
217
218
219

220
221
222
223
224
225
226
208
209
210
211
212
213
214

215
216
217
218

219
220
221
222
223
224
225
226







-
+



-
+








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

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

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

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

250
251
252
253
254
255
256
257

258
259
260

261
262
263
264
265
266
267
250
251
252
253
254
255
256

257
258
259

260
261
262
263
264
265
266
267







-
+


-
+








	if (![self isKindOfClass: [OFMutableArray class]])
		return [OFArray_adjacentSubarray arrayWithArray: self
							  range: range];

	count = [array count];

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

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

- (BOOL)isEqual: (id)object
{
	OFArray *otherArray;
	id *objects, *otherObjects;

Modified src/OFArray_adjacentSubarray.m from [eb001a037a] to [27e54c8e9a].

19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







-
+







#import "OFArray_adjacentSubarray.h"
#import "OFArray_adjacent.h"
#import "OFMutableArray_adjacent.h"

@implementation OFArray_adjacentSubarray
- (id*)objects
{
	return [array objects] + range.start;
	return [array objects] + range.location;
}

- (BOOL)isEqual: (id)object
{
	OFArray *otherArray;
	id *objects, *otherObjects;
	size_t i;

Modified src/OFArray_subarray.m from [3219b4036a] to [9c788f37d8].

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







-
+





-
+


-
+









-
+


-
+











-
+


-
+









-
+


-
+




}

- (id)objectAtIndex: (size_t)index
{
	if (index >= range.length)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	return [array objectAtIndex: index + range.start];
	return [array objectAtIndex: index + range.location];
}

- (void)getObjects: (id*)buffer
	   inRange: (of_range_t)range_
{
	if (range_.start + range_.length > range.length)
	if (range_.location + range_.length > range.length)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	range_.start += range.start;
	range_.location += range.location;

	return [array getObjects: buffer
			 inRange: range_];
}

- (size_t)indexOfObject: (id)object
{
	size_t index = [array indexOfObject: object];

	if (index < range.start)
	if (index < range.location)
		return OF_INVALID_INDEX;

	index -= range.start;
	index -= range.location;

	if (index >= range.length)
		return OF_INVALID_INDEX;

	return index;
}

- (size_t)indexOfObjectIdenticalTo: (id)object
{
	size_t index = [array indexOfObjectIdenticalTo: object];

	if (index < range.start)
	if (index < range.location)
		return OF_INVALID_INDEX;

	index -= range.start;
	index -= range.location;

	if (index >= range.length)
		return OF_INVALID_INDEX;

	return index;
}

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

	range_.start += range.start;
	range_.location += range.location;

	return [array objectsInRange: range_];
}
@end

Modified src/OFDataArray.m from [191802fe3a] to [95b4b4e97a].

373
374
375
376
377
378
379
380

381
382
383
384
385



386
387
388
389
390
391
392
373
374
375
376
377
378
379

380
381
382



383
384
385
386
387
388
389
390
391
392







-
+


-
-
-
+
+
+







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

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

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

	count -= range.length;
	@try {
		data = [self resizeMemory: data
				     size: itemSize
				    count: count];
	} @catch (OFOutOfMemoryException *e) {
636
637
638
639
640
641
642
643

644
645
646
647
648



649
650
651
652
653
654
655
636
637
638
639
640
641
642

643
644
645



646
647
648
649
650
651
652
653
654
655







-
+


-
-
-
+
+
+







	size = newSize;
}

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

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

	memmove(data + range.start * itemSize,
	    data + (range.start + range.length) * itemSize,
	    (count - range.start - range.length) * itemSize);
	memmove(data + range.location * itemSize,
	    data + (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

Modified src/OFHTTPRequest.m from [bc400146e4] to [997525c718].

409
410
411
412
413
414
415
416

417
418

419
420
421
422
423
424
425
409
410
411
412
413
414
415

416
417

418
419
420
421
422
423
424
425







-
+

-
+







					line = [sock readLine];
				} @catch (OFInvalidEncodingException *e) {
					@throw [OFInvalidServerReplyException
					    exceptionWithClass: [self class]];
				}

				range = [line rangeOfString: @";"];
				if (range.start != OF_INVALID_INDEX)
				if (range.location != OF_INVALID_INDEX)
					line = [line substringWithRange:
					    of_range(0, range.start)];
					    of_range(0, range.location)];

				@try {
					toRead =
					    (size_t)[line hexadecimalValue];
				} @catch (OFInvalidFormatException *e) {
					@throw [OFInvalidServerReplyException
					    exceptionWithClass: [self class]];

Modified src/OFMutableArray.m from [b2cd72f318] to [b32d8ba01b].

292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306







-
+







}

- (void)removeObjectsInRange: (of_range_t)range
{
	size_t i;

	for (i = 0; i < range.length; i++)
		[self removeObjectAtIndex: range.start];
		[self removeObjectAtIndex: range.location];
}

- (void)removeLastObject
{
	size_t count = [self count];

	if (count > 0)

Modified src/OFMutableArray_adjacent.m from [b8f5cd2bb5] to [35095fc2a7].

172
173
174
175
176
177
178
179

180
181
182
183
184

185
186
187
188
189
190
191
172
173
174
175
176
177
178

179
180
181
182
183

184
185
186
187
188
189
190
191







-
+




-
+







}

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

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

	copy = [self allocMemoryWithSize: sizeof(*copy)
				   count: range.length];
	memcpy(copy, objects + range.start, range.length * sizeof(id));
	memcpy(copy, objects + range.location, range.length * sizeof(id));

	@try {
		[array removeItemsInRange: range];
		mutations++;

		for (i = 0; i < range.length; i++)
			[copy[i] release];

Modified src/OFMutableString.m from [ee0cfc9cd4] to [0b9877e248].

446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460







-
+







}

- (void)replaceCharactersInRange: (of_range_t)range
		      withString: (OFString*)replacement
{
	[self deleteCharactersInRange: range];
	[self insertString: replacement
		   atIndex: range.start];
		   atIndex: range.location];
}

- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement
{
	[self replaceOccurrencesOfString: string
			      withString: replacement
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
468
469
470
471
472
473
474

475
476
477
478
479
480
481
482
483
484
485

486
487
488
489
490
491
492
493







-
+










-
+







	void *pool = objc_autoreleasePoolPush(), *pool2;
	const of_unichar_t *unicodeString;
	const of_unichar_t *searchString = [string unicodeString];
	size_t searchLength = [string length];
	size_t replacementLength = [replacement length];
	size_t i;

	if (range.start + range.length > [self length])
	if (range.location + range.length > [self length])
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	if (searchLength > range.length) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	pool2 = objc_autoreleasePoolPush();
	unicodeString = [self unicodeString];

	for (i = range.start; i <= range.length - searchLength; i++) {
	for (i = range.location; i <= range.length - searchLength; i++) {
		if (memcmp(unicodeString + i, searchString,
		    searchLength * sizeof(of_unichar_t)))
			continue;

		[self replaceCharactersInRange: of_range(i, searchLength)
				    withString: replacement];

Modified src/OFMutableString_UTF8.m from [34bbb5a839] to [b5e0c44310].

526
527
528
529
530
531
532
533
534


535
536
537
538
539
540
541
526
527
528
529
530
531
532


533
534
535
536
537
538
539
540
541







-
-
+
+







			s->isUTF8 = YES;
	} else
		s->isUTF8 = YES;
}

- (void)deleteCharactersInRange: (of_range_t)range
{
	size_t start = range.start;
	size_t end = range.start + range.length;
	size_t start = range.location;
	size_t end = range.location + range.length;

	if (end > s->length)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	s->hashed = NO;
	s->length -= end - start;

557
558
559
560
561
562
563
564
565


566
567
568
569
570
571
572
557
558
559
560
561
562
563


564
565
566
567
568
569
570
571
572







-
-
+
+







		/* We don't really care, as we only made it smaller */
	}
}

- (void)replaceCharactersInRange: (of_range_t)range
		      withString: (OFString*)replacement
{
	size_t start = range.start;
	size_t end = range.start + range.length;
	size_t start = range.location;
	size_t end = range.location + range.length;
	size_t newCStringLength, newLength;

	if (end > s->length)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	newLength = s->length - (end - start) + [replacement length];

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







-
-
-
-
+
+
+
+
+


-
+









+
-
+







	const char *replacementString = [replacement UTF8String];
	size_t searchLength = [string UTF8StringLength];
	size_t replacementLength = [replacement UTF8StringLength];
	size_t i, last, newCStringLength, newLength;
	char *newCString;

	if (s->isUTF8) {
		range.start = of_string_utf8_get_position(s->cString,
		    range.start, s->cStringLength);
		range.length = of_string_utf8_get_position(s->cString,
		    range.start + range.length, s->cStringLength) - range.start;
		range.location = of_string_utf8_get_position(s->cString,
		    range.location, s->cStringLength);
		range.length = of_string_utf8_get_position(
		    s->cString + range.location, range.length,
		    s->cStringLength - range.location);
	}

	if (range.start + range.length > [self UTF8StringLength])
	if (range.location + range.length > [self UTF8StringLength])
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	if ([string UTF8StringLength] > range.length)
		return;

	newCString = NULL;
	newCStringLength = 0;
	newLength = s->length;

	last = 0;
	for (i = range.start, last = 0; i <= range.length - searchLength; i++) {
	for (i = range.location; i <= range.length - searchLength; i++) {
		if (memcmp(s->cString + i, searchString, searchLength))
			continue;

		@try {
			newCString = [self
			    resizeMemory: newCString
				    size: newCStringLength + i - last +

Modified src/OFNull.m from [145485c3f5] to [469bfd7104].

24
25
26
27
28
29
30
31

32
33

34
35
36
37




38
39
40
41
42
43
44
24
25
26
27
28
29
30

31
32

33




34
35
36
37
38
39
40
41
42
43
44







-
+

-
+
-
-
-
-
+
+
+
+







#import "OFNotImplementedException.h"

#import "autorelease.h"

static OFNull *null = nil;

@implementation OFNull
+ (OFNull*)null
+ (void)initialize
{
	if (null != nil)
	null = [[self alloc] init];
		return null;

	null = [[self alloc] init];

}

+ (OFNull*)null
{
	return null;
}

- initWithSerialization: (OFXMLElement*)element
{
	void *pool;

Modified src/OFObject.h from [2329ee91b2] to [b910dda1d9].

123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137







-
+







} of_byte_order_t;

/**
 * \brief A range.
 */
typedef struct of_range_t {
	/// The start of the range
	size_t start;
	size_t location;
	/// The length of the range
	size_t length;
} of_range_t;

/**
 * \brief A point.
 */

Modified src/OFString.m from [9f1383c46f] to [651cb0fc54].

925
926
927
928
929
930
931
932

933
934
935
936
937
938
939
925
926
927
928
929
930
931

932
933
934
935
936
937
938
939







-
+








- (void)getCharacters: (of_unichar_t*)buffer
	      inRange: (of_range_t)range
{
	size_t i;

	for (i = 0; i < range.length; i++)
		buffer[i] = [self characterAtIndex: range.start + i];
		buffer[i] = [self characterAtIndex: range.location + i];
}

- (BOOL)isEqual: (id)object
{
	void *pool;
	OFString *otherString;
	const of_unichar_t *unicodeString, *otherUnicodeString;
1203
1204
1205
1206
1207
1208
1209
1210

1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223

1224
1225
1226
1227
1228
1229
1230
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
1230







-
+












-
+







			    inRange: range];

		if (options & OF_STRING_SEARCH_BACKWARDS) {
			for (i = range.length - searchLength;; i--) {
				if (!memcmp(unicodeString + i, searchString,
				    searchLength * sizeof(of_unichar_t))) {
					objc_autoreleasePoolPop(pool);
					return of_range(range.start + i,
					return of_range(range.location + i,
					    searchLength);
				}

				/* No match and we're at the last character */
				if (i == 0)
					break;
			}
		} else {
			for (i = 0; i <= range.length - searchLength; i++) {
				if (!memcmp(unicodeString + i, searchString,
				    searchLength * sizeof(of_unichar_t))) {
					objc_autoreleasePoolPop(pool);
					return of_range(range.start + i,
					return of_range(range.location + i,
					    searchLength);
				}
			}
		}
	} @finally {
		free(unicodeString);
	}
1265
1266
1267
1268
1269
1270
1271
1272

1273
1274
1275
1276
1277
1278

1279
1280
1281
1282
1283
1284
1285
1265
1266
1267
1268
1269
1270
1271

1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1285







-
+





-
+







}

- (OFString*)substringWithRange: (of_range_t)range
{
	void *pool;
	OFString *ret;

	if (range.start + range.length > [self length])
	if (range.location + range.length > [self length])
		@throw [OFOutOfRangeException
		    exceptionWithClass: [self class]];

	pool = objc_autoreleasePoolPush();
	ret = [[OFString alloc]
	    initWithUnicodeString: [self unicodeString] + range.start
	    initWithUnicodeString: [self unicodeString] + range.location
			   length: range.length];
	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString*)stringByAppendingString: (OFString*)string

Modified src/OFString_UTF8.m from [f8f277011d] to [e621285ff6].

1027
1028
1029
1030
1031
1032
1033
1034

1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055

1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070

1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1027
1028
1029
1030
1031
1032
1033

1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084

1085
1086
1087
1088
1089
1090
1091
1092







-
+















-
+




-
+














-
+














-
+







- (void)getCharacters: (of_unichar_t*)buffer
	      inRange: (of_range_t)range
{
	/* TODO: Could be slightly optimized */
	void *pool = objc_autoreleasePoolPush();
	const of_unichar_t *unicodeString = [self unicodeString];

	memcpy(buffer, unicodeString + range.start,
	memcpy(buffer, unicodeString + range.location,
	    range.length * sizeof(of_unichar_t));

	objc_autoreleasePoolPop(pool);
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (of_string_search_options_t)options
		      range: (of_range_t)range
{
	const char *cString = [string UTF8String];
	size_t i, cStringLength = [string UTF8StringLength];
	size_t rangeStart, rangeLength;

	if (s->isUTF8) {
		rangeStart = of_string_utf8_get_position(
		    s->cString, range.start, s->cStringLength);
		    s->cString, range.location, s->cStringLength);
		rangeLength = of_string_utf8_get_position(
		    s->cString + rangeStart, range.length,
		    s->cStringLength - rangeStart);
	} else {
		rangeStart = range.start;
		rangeStart = range.location;
		rangeLength = range.length;
	}

	if (cStringLength == 0)
		return of_range(0, 0);

	if (cStringLength > rangeLength ||
	    rangeStart + rangeLength > s->cStringLength)
		return of_range(OF_INVALID_INDEX, 0);

	if (options & OF_STRING_SEARCH_BACKWARDS) {
		for (i = rangeLength - cStringLength;; i--) {
			if (!memcmp(s->cString + rangeStart + i, cString,
			    cStringLength)) {
				range.start += of_string_utf8_get_index(
				range.location += of_string_utf8_get_index(
				    s->cString + rangeStart, i);
				range.length = [string length];

				return range;
			}

			/* Did not match and we're at the last char */
			if (i == 0)
				return of_range(OF_INVALID_INDEX, 0);
		}
	} else {
		for (i = 0; i <= rangeLength - cStringLength; i++) {
			if (!memcmp(s->cString + rangeStart + i, cString,
			    cStringLength)) {
				range.start += of_string_utf8_get_index(
				range.location += of_string_utf8_get_index(
				    s->cString + rangeStart, i);
				range.length = [string length];

				return range;
			}
		}
	}
1110
1111
1112
1113
1114
1115
1116
1117
1118


1119
1120
1121
1122
1123
1124
1125
1110
1111
1112
1113
1114
1115
1116


1117
1118
1119
1120
1121
1122
1123
1124
1125







-
-
+
+







			return YES;

	return NO;
}

- (OFString*)substringWithRange: (of_range_t)range
{
	size_t start = range.start;
	size_t end = range.start + range.length;
	size_t start = range.location;
	size_t end = range.location + range.length;

	if (end > s->length)
		@throw [OFOutOfRangeException exceptionWithClass: [self class]];

	if (s->isUTF8) {
		start = of_string_utf8_get_position(s->cString, start,
		    s->cStringLength);

Modified tests/OFStringTests.m from [6fb7a36b8d] to [42e3523e42].

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







-
-
-
-
+
+
+
+

-
+

-
+

-
+

-
+







	    isEqual: @"test:123"])

	TEST(@"-[appendFormat:]",
	    R(([s[0] appendFormat: @"%02X", 15])) &&
	    [s[0] isEqual: @"test:1230F"])

	TEST(@"-[rangeOfString:]",
	    [@"π„žΓΆΓΆ" rangeOfString: @"ΓΆΓΆ"].start == 1 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"ΓΆ"].start == 1 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"π„ž"].start == 0 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"x"].start == OF_INVALID_INDEX &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"ΓΆΓΆ"].location == 1 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"ΓΆ"].location == 1 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"π„ž"].location == 0 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"x"].location == OF_INVALID_INDEX &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"ΓΆΓΆ"
			  options: OF_STRING_SEARCH_BACKWARDS].start == 1 &&
			  options: OF_STRING_SEARCH_BACKWARDS].location == 1 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"ΓΆ"
			  options: OF_STRING_SEARCH_BACKWARDS].start == 2 &&
			  options: OF_STRING_SEARCH_BACKWARDS].location == 2 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"π„ž"
			  options: OF_STRING_SEARCH_BACKWARDS].start == 0 &&
			  options: OF_STRING_SEARCH_BACKWARDS].location == 0 &&
	    [@"π„žΓΆΓΆ" rangeOfString: @"x"
			  options: OF_STRING_SEARCH_BACKWARDS].start ==
			  options: OF_STRING_SEARCH_BACKWARDS].location ==
	     OF_INVALID_INDEX)

	TEST(@"-[substringWithRange:]",
	    [[@"π„žΓΆΓΆ" substringWithRange: of_range(1, 1)] isEqual: @"ΓΆ"] &&
	    [[@"π„žΓΆΓΆ" substringWithRange: of_range(3, 0)] isEqual: @""])

	EXPECT_EXCEPTION(@"Detect out of range in -[substringWithRange:] #1",