ObjFW  Check-in [2b615e0443]

Overview
Comment:Indexes are now relative to the Unicode character, not the C character.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2b615e0443838500152870e7f3c7f2959bdfdd6b81a9ae3dc158a8f3dd337434
User & Date: js on 2009-10-03 20:41:26
Other Links: manifest | tags
Context
2009-10-03
21:12
Fix setting of is_utf8. check-in: f01153154d user: js tags: trunk
20:41
Indexes are now relative to the Unicode character, not the C character. check-in: 2b615e0443 user: js tags: trunk
13:38
Rename tests_new to tests. check-in: 81239da84f user: js tags: trunk
Changes

Modified src/OFMutableString.m from [c3c573eb68] to [e137055b69].

291
292
293
294
295
296
297



298
299
300
301
302
303
304

	return self;
}

- removeCharactersFromIndex: (size_t)start
		    toIndex: (size_t)end
{



	if (start > end)
		@throw [OFInvalidArgumentException newWithClass: isa
						       selector: _cmd];

	if (end > length)
		@throw [OFOutOfRangeException newWithClass: isa];








>
>
>







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

	return self;
}

- removeCharactersFromIndex: (size_t)start
		    toIndex: (size_t)end
{
	start = of_string_index_to_position(string, start, length);
	end = of_string_index_to_position(string, end, length);

	if (start > end)
		@throw [OFInvalidArgumentException newWithClass: isa
						       selector: _cmd];

	if (end > length)
		@throw [OFOutOfRangeException newWithClass: isa];

Modified src/OFString.h from [db05d342fe] to [4beff4fcbf].

20
21
22
23
24
25
26


27
28
29
30
31
32
33
	OF_STRING_ENCODING_ISO_8859_1,
	OF_STRING_ENCODING_ISO_8859_15,
	OF_STRING_ENCODING_WINDOWS_1252
};

extern int of_string_check_utf8(const char*, size_t);
extern size_t of_string_unicode_to_utf8(uint32_t, char*);



/**
 * A class for managing strings.
 */
@interface OFString: OFObject <OFCopying, OFMutableCopying>
{
	char	     *string;







>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
	OF_STRING_ENCODING_ISO_8859_1,
	OF_STRING_ENCODING_ISO_8859_15,
	OF_STRING_ENCODING_WINDOWS_1252
};

extern int of_string_check_utf8(const char*, size_t);
extern size_t of_string_unicode_to_utf8(uint32_t, char*);
extern size_t of_string_position_to_index(const char*, size_t);
extern size_t of_string_index_to_position(const char*, size_t, size_t);

/**
 * A class for managing strings.
 */
@interface OFString: OFObject <OFCopying, OFMutableCopying>
{
	char	     *string;

Modified src/OFString.m from [e5d0b3d2f0] to [329139cf3c].

135
136
137
138
139
140
141

























142
143
144
145
146
147
148
		buf[i++] = 0x80 | (c >> 6 & 0x3F);
		buf[i] = 0x80 | (c & 0x3F);
		return 4;
	}

	return 0;
}


























@implementation OFString
+ string
{
	return [[[self alloc] init] autorelease];
}








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







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
		buf[i++] = 0x80 | (c >> 6 & 0x3F);
		buf[i] = 0x80 | (c & 0x3F);
		return 4;
	}

	return 0;
}

size_t
of_string_position_to_index(const char *str, size_t pos)
{
	size_t i, idx = pos;

	for (i = 0; i < pos; i++)
		if (OF_UNLIKELY((str[i] & 0xC0) == 0x80))
			idx--;

	return idx;
}

size_t
of_string_index_to_position(const char *str, size_t idx, size_t len)
{
	size_t i;

	for (i = 0; i <= idx; i++)
		if (OF_UNLIKELY((str[i] & 0xC0) == 0x80))
			if (++idx > len)
				return SIZE_MAX;

	return idx;
}

@implementation OFString
+ string
{
	return [[[self alloc] init] autorelease];
}

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
		return 0;

	if (str_len > length)
		return SIZE_MAX;

	for (i = 0; i <= length - str_len; i++)
		if (!memcmp(string + i, str_c, str_len))
			return i;

	return SIZE_MAX;
}

- (size_t)indexOfLastOccurrenceOfString: (OFString*)str
{
	const char *str_c = [str cString];
	size_t str_len = [str cStringLength];
	size_t i;

	if (str_len == 0)
		return length;

	if (str_len > length)
		return SIZE_MAX;

	for (i = length - str_len;; i--) {
		if (!memcmp(string + i, str_c, str_len))
			return i;

		/* Did not match and we're at the last char */
		if (i == 0)
			return SIZE_MAX;
	}
}

- (OFString*)substringFromIndex: (size_t)start
			toIndex: (size_t)end
{



	if (start > end)
		@throw [OFInvalidArgumentException newWithClass: isa
						       selector: _cmd];

	if (end > length)
		@throw [OFOutOfRangeException newWithClass: isa];








|











|






|










>
>
>







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
576
577
578
579
580
581
582
583
584
585
586
587
588
		return 0;

	if (str_len > length)
		return SIZE_MAX;

	for (i = 0; i <= length - str_len; i++)
		if (!memcmp(string + i, str_c, str_len))
			return of_string_position_to_index(string, i);

	return SIZE_MAX;
}

- (size_t)indexOfLastOccurrenceOfString: (OFString*)str
{
	const char *str_c = [str cString];
	size_t str_len = [str cStringLength];
	size_t i;

	if (str_len == 0)
		return of_string_position_to_index(string, length);

	if (str_len > length)
		return SIZE_MAX;

	for (i = length - str_len;; i--) {
		if (!memcmp(string + i, str_c, str_len))
			return of_string_position_to_index(string, i);

		/* Did not match and we're at the last char */
		if (i == 0)
			return SIZE_MAX;
	}
}

- (OFString*)substringFromIndex: (size_t)start
			toIndex: (size_t)end
{
	start = of_string_index_to_position(string, start, length);
	end = of_string_index_to_position(string, end, length);

	if (start > end)
		@throw [OFInvalidArgumentException newWithClass: isa
						       selector: _cmd];

	if (end > length)
		@throw [OFOutOfRangeException newWithClass: isa];

Modified tests/string.m from [01f5951778] to [34e88502ac].

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
	    [(s[0] = [OFMutableString stringWithFormat: @"%s: %d", "test", 123])
	    isEqual: @"test: 123"])

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

	TEST(@"-[indexOfFirstOccurrenceOfString:]",
	    [@"foo" indexOfFirstOccurrenceOfString: @"oo"] == 1 &&
	    [@"foo" indexOfFirstOccurrenceOfString: @"o"] == 1 &&
	    [@"foo" indexOfFirstOccurrenceOfString: @"f"] == 0 &&
	    [@"foo" indexOfFirstOccurrenceOfString: @"x"] == SIZE_MAX)

	TEST(@"-[indexOfLastOccurrenceOfString:]",
	    [@"foo" indexOfLastOccurrenceOfString: @"oo"] == 1 &&
	    [@"foo" indexOfLastOccurrenceOfString: @"o"] == 2 &&
	    [@"foo" indexOfLastOccurrenceOfString: @"f"] == 0 &&
	    [@"foo" indexOfLastOccurrenceOfString: @"x"] == SIZE_MAX)

	TEST(@"-[substringFromIndexToIndex:]",
	    [[@"foo" substringFromIndex: 1
				toIndex: 2] isEqual: @"o"] &&
	    [[@"foo" substringFromIndex: 3
				toIndex: 3] isEqual: @""])

	EXPECT_EXCEPTION(@"Detect out of range in "
	    @"-[substringFromIndex:toIndex:] #1", OFOutOfRangeException,
	    [@"foo" substringFromIndex: 2
			       toIndex: 4])
	EXPECT_EXCEPTION(@"Detect out of range in "
	    @"-[substringFromIndex:toIndex:] #2", OFOutOfRangeException,
	    [@"foo" substringFromIndex: 4
			       toIndex: 4])

	EXPECT_EXCEPTION(@"Detect start > end in "
	    @"-[substringFromIndex:toIndex:]", OFInvalidArgumentException,
	    [@"foo" substringFromIndex: 2
			       toIndex: 0])

	TEST(@"-[stringByAppendingString:]",
	    [[@"foo" stringByAppendingString: @"bar"] isEqual: @"foobar"])

	TEST(@"-[hasPrefix:]", [@"foobar" hasPrefix: @"foo"] &&
	    ![@"foobar" hasPrefix: @"foobar0"])







|
|
|
|


|
|
|
|


|
|
|




|



|




|







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
	    [(s[0] = [OFMutableString stringWithFormat: @"%s: %d", "test", 123])
	    isEqual: @"test: 123"])

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

	TEST(@"-[indexOfFirstOccurrenceOfString:]",
	    [@"π„žΓΆΓΆ" indexOfFirstOccurrenceOfString: @"ΓΆΓΆ"] == 1 &&
	    [@"π„žΓΆΓΆ" indexOfFirstOccurrenceOfString: @"ΓΆ"] == 1 &&
	    [@"π„žΓΆΓΆ" indexOfFirstOccurrenceOfString: @"π„ž"] == 0 &&
	    [@"π„žΓΆΓΆ" indexOfFirstOccurrenceOfString: @"x"] == SIZE_MAX)

	TEST(@"-[indexOfLastOccurrenceOfString:]",
	    [@"π„žΓΆΓΆ" indexOfLastOccurrenceOfString: @"ΓΆΓΆ"] == 1 &&
	    [@"π„žΓΆΓΆ" indexOfLastOccurrenceOfString: @"ΓΆ"] == 2 &&
	    [@"π„žΓΆΓΆ" indexOfLastOccurrenceOfString: @"π„ž"] == 0 &&
	    [@"π„žΓΆΓΆ" indexOfLastOccurrenceOfString: @"x"] == SIZE_MAX)

	TEST(@"-[substringFromIndexToIndex:]",
	    [[@"π„žΓΆΓΆ" substringFromIndex: 1
				toIndex: 2] isEqual: @"ΓΆ"] &&
	    [[@"π„žΓΆΓΆ" substringFromIndex: 3
				toIndex: 3] isEqual: @""])

	EXPECT_EXCEPTION(@"Detect out of range in "
	    @"-[substringFromIndex:toIndex:] #1", OFOutOfRangeException,
	    [@"π„žΓΆΓΆ" substringFromIndex: 2
			       toIndex: 4])
	EXPECT_EXCEPTION(@"Detect out of range in "
	    @"-[substringFromIndex:toIndex:] #2", OFOutOfRangeException,
	    [@"π„žΓΆΓΆ" substringFromIndex: 4
			       toIndex: 4])

	EXPECT_EXCEPTION(@"Detect start > end in "
	    @"-[substringFromIndex:toIndex:]", OFInvalidArgumentException,
	    [@"π„žΓΆΓΆ" substringFromIndex: 2
			       toIndex: 0])

	TEST(@"-[stringByAppendingString:]",
	    [[@"foo" stringByAppendingString: @"bar"] isEqual: @"foobar"])

	TEST(@"-[hasPrefix:]", [@"foobar" hasPrefix: @"foo"] &&
	    ![@"foobar" hasPrefix: @"foobar0"])
180
181
182
183
184
185
186
187
188
189
190
191
192
193



















194
195
196
197
198
199
200
	EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] "
	    @"#1", OFInvalidEncodingException, [@"foo%bar" stringByURLDecoding])
	EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] "
	    @"#2", OFInvalidEncodingException,
	    [@"foo%FFbar" stringByURLDecoding])

	TEST(@"-[removeCharactersFromIndex:toIndex:]",
	    (s[0] = [OFMutableString stringWithString: @"fooobar"]) &&
	    [s[0] removeCharactersFromIndex: 1
				    toIndex: 4] &&
	    [s[0] isEqual: @"fbar"] &&
	    [s[0] removeCharactersFromIndex: 0
				    toIndex: 4] &&
	    [s[0] isEqual: @""])




















	TEST(@"-[replaceOccurrencesOfString:withString:]",
	    [[[OFMutableString stringWithString: @"asd fo asd fofo asd"]
	    replaceOccurrencesOfString: @"fo"
			    withString: @"foo"]
	    isEqual: @"asd foo asd foofoo asd"] &&
	    [[[OFMutableString stringWithString: @"XX"]







|


|



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







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
	EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] "
	    @"#1", OFInvalidEncodingException, [@"foo%bar" stringByURLDecoding])
	EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] "
	    @"#2", OFInvalidEncodingException,
	    [@"foo%FFbar" stringByURLDecoding])

	TEST(@"-[removeCharactersFromIndex:toIndex:]",
	    (s[0] = [OFMutableString stringWithString: @"π„žΓΆΓΆΓΆbÀ€"]) &&
	    [s[0] removeCharactersFromIndex: 1
				    toIndex: 4] &&
	    [s[0] isEqual: @"π„žbÀ€"] &&
	    [s[0] removeCharactersFromIndex: 0
				    toIndex: 4] &&
	    [s[0] isEqual: @""])

	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[removeCharactersFromIndex:toIndex:] #1", OFOutOfRangeException,
	    {
		s[0] = [OFMutableString stringWithString: @"π„žΓΆΓΆ"];
		[s[0] substringFromIndex: 2
				 toIndex: 4];
	    })

	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[removeCharactersFromIndex:toIndex:] #2", OFOutOfRangeException,
	    [s[0] substringFromIndex: 4
			     toIndex: 4])

	EXPECT_EXCEPTION(@"Detect s > e in "
	    @"-[removeCharactersFromIndex:toIndex:]",
	    OFInvalidArgumentException,
	    [s[0] substringFromIndex: 2
			     toIndex: 0])

	TEST(@"-[replaceOccurrencesOfString:withString:]",
	    [[[OFMutableString stringWithString: @"asd fo asd fofo asd"]
	    replaceOccurrencesOfString: @"fo"
			    withString: @"foo"]
	    isEqual: @"asd foo asd foofoo asd"] &&
	    [[[OFMutableString stringWithString: @"XX"]