ObjFW  Check-in [e7e8efd297]

Overview
Comment:More separation for OFString and OFMutableString.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e7e8efd2975a632015c1f5a76c61a9c1e4ed9a5dc55a051eb75ce0e2322965fa
User & Date: js on 2009-05-18 18:09:08
Other Links: manifest | tags
Context
2009-05-18
18:15
Introduce OFMutableCopying protocol. check-in: 79e1893b40 user: js tags: trunk
18:09
More separation for OFString and OFMutableString. check-in: e7e8efd297 user: js tags: trunk
17:50
Split OFArray into OFArray and OFMutableArray. check-in: 163409967e user: js tags: trunk
Changes

Modified src/OFMutableString.h from [0dde8a8b94] to [50d5f8f8b9].

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

#import "OFString.h"

/**
 * A class for storing and modifying strings.
 */
@interface OFMutableString: OFString
{
	BOOL   is_utf8;
}

/**
 * Initializes an already allocated OFMutableString from a C string.
 *
 * \param str A C string to initialize the OFMutableString with
 * \return An initialized OFMutableString
 */
- initWithCString: (const char*)str;

/**
 * Initializes an already allocated OFMutableString from a format C string.
 * See printf for the format syntax.
 *
 * \param fmt A string used as format to initialize the OFMutableString
 * \return An initialized OFMutableString
 */
- initWithFormat: (OFString*)fmt, ...;

/**
 * Initializes an already allocated OFMutableString from a format C string.
 * See printf for the format syntax.
 *
 * \param fmt A string used as format to initialize the OFMutableString
 * \param args The arguments used in the format string
 * \return An initialized OFMutableString
 */
- initWithFormat: (OFString*)fmt
    andArguments: (va_list)args;
@end







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

14
15
16
17
18
19
20































21

#import "OFString.h"

/**
 * A class for storing and modifying strings.
 */
@interface OFMutableString: OFString































@end

Modified src/OFMutableString.m from [9dc4884694] to [61830ce984].

8
9
10
11
12
13
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
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
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
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "config.h"

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>

#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#else
#define madvise(addr, len, advise)
#endif

#import "OFMutableString.h"
#import "OFExceptions.h"
#import "OFMacros.h"

#ifndef HAVE_ASPRINTF
#import "asprintf.h"
#endif

static OF_INLINE int
check_utf8(const char *str, size_t len)
{
	size_t i;
	BOOL utf8;

	utf8 = NO;

	madvise((void*)str, len, MADV_SEQUENTIAL);

	for (i = 0; i < len; i++) {
		/* No sign of UTF-8 here */
		if (OF_LIKELY(!(str[i] & 0x80)))
			continue;

		utf8 = YES;

		/* We're missing a start byte here */
		if (OF_UNLIKELY(!(str[i] & 0x40))) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		/* We have at minimum a 2 byte character -> check next byte */
		if (OF_UNLIKELY(len < i + 1 || (str[i + 1] & 0xC0) != 0x80)) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		/* Check if we have at minimum a 3 byte character */
		if (OF_LIKELY(!(str[i] & 0x20))) {
			i++;
			continue;
		}

		/* We have at minimum a 3 byte char -> check second next byte */
		if (OF_UNLIKELY(len < i + 2 || (str[i + 2] & 0xC0) != 0x80)) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		/* Check if we have a 4 byte character */
		if (OF_LIKELY(!(str[i] & 0x10))) {
			i += 2;
			continue;
		}

		/* We have a 4 byte character -> check third next byte */
		if (OF_UNLIKELY(len < i + 3 || (str[i + 3] & 0xC0) != 0x80)) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		/*
		 * Just in case, check if there's a 5th character, which is
		 * forbidden by UTF-8
		 */
		if (OF_UNLIKELY(str[i] & 0x08)) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		i += 3;
	}

	madvise((void*)str, len, MADV_NORMAL);

	return (utf8 ? 1 : 0);
}

@implementation OFMutableString
- initWithCString: (const char*)str
{
	Class c;

	self = [super init];

	if (str != NULL) {
		length = strlen(str);

		switch (check_utf8(str, length)) {
			case 1:
				is_utf8 = YES;
				break;
			case -1:
				c = isa;
				[super dealloc];
				@throw [OFInvalidEncodingException
					newWithClass: c];
		}

		@try {
			string = [self allocWithSize: length + 1];
		} @catch (OFException *e) {
			/*
			 * We can't use [super dealloc] on OS X here.
			 * Compiler bug? Anyway, [self dealloc] will do here as
			 * we don't reimplement dealloc.
			 */
			[self dealloc];
			@throw e;
		}
		memcpy(string, str, length + 1);
	}

	return self;
}

- initWithFormat: (OFString*)fmt, ...
{
	id ret;
	va_list args;

	va_start(args, fmt);
	ret = [self initWithFormat: fmt
		      andArguments: args];
	va_end(args);

	return ret;
}

- initWithFormat: (OFString*)fmt
    andArguments: (va_list)args
{
	int t;
	Class c;

	self = [super init];

	if (fmt == NULL) {
		c = isa;
		[super dealloc];
		@throw [OFInvalidFormatException newWithClass: c];
	}

	if ((t = vasprintf(&string, [fmt cString], args)) == -1) {
		c = isa;
		[super dealloc];
		@throw [OFInitializationFailedException newWithClass: c];
	}
	length = t;

	switch (check_utf8(string, length)) {
		case 1:
			is_utf8 = YES;
			break;
		case -1:
			free(string);
			c = isa;
			[super dealloc];
			@throw [OFInvalidEncodingException newWithClass: c];
	}

	@try {
		[self addToMemoryPool: string];
	} @catch (OFException *e) {
		free(string);
		@throw e;
	}

	return self;
}

- setTo: (const char*)str
{
	size_t len;

	if (string != NULL)
		[self freeMem: string];

	len = strlen(str);

	switch (check_utf8(str, len)) {
	case 1:
		is_utf8 = YES;
		break;
	case -1:
		string = NULL;
		length = 0;
		is_utf8 = NO;







|
|
|

















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








|







8
9
10
11
12
13
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
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "config.h"

#define _GNU_SOURCE
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#else
#define madvise(addr, len, advise)
#endif

#import "OFMutableString.h"
#import "OFExceptions.h"
#import "OFMacros.h"

#ifndef HAVE_ASPRINTF
#import "asprintf.h"
#endif







































































@implementation OFMutableString
- setToCString: (const char*)str




























































































{
	size_t len;

	if (string != NULL)
		[self freeMem: string];

	len = strlen(str);

	switch (of_string_check_utf8(str, len)) {
	case 1:
		is_utf8 = YES;
		break;
	case -1:
		string = NULL;
		length = 0;
		is_utf8 = NO;
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

- appendCString: (const char*)str
{
	size_t strlength;

	strlength = strlen(str);

	switch (check_utf8(str, strlength)) {
	case 1:
		is_utf8 = YES;
		break;
	case -1:
		@throw [OFInvalidEncodingException newWithClass: isa];
	}








|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

- appendCString: (const char*)str
{
	size_t strlength;

	strlength = strlen(str);

	switch (of_string_check_utf8(str, strlength)) {
	case 1:
		is_utf8 = YES;
		break;
	case -1:
		@throw [OFInvalidEncodingException newWithClass: isa];
	}

Modified src/OFString.h from [71d4835865] to [b7ca2d5c06].

11
12
13
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
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

#include <stdio.h>
#include <stdarg.h>

#import "OFObject.h"
#import "OFArray.h"



/**
 * A class for managing strings.
 */
@interface OFString: OFObject <OFCopying>
{
	char	     *string;
#ifdef __objc_INCLUDE_GNU
	unsigned int length;
#else
	int	     length;
#if __LP64__
	int	     _unused;
#endif
#endif

}

/**
 * \return A new autoreleased OFMutableString
 */
+ string;

/**
 * Creates a new OFMutableString from a C string.
 *
 * \param str A C string to initialize the OFMutableString with
 * \return A new autoreleased OFMutableString
 */
+ stringWithCString: (const char*)str;

/**
 * Creates a new OFMutableString from a format C string.
 * See printf for the format syntax.
 *
 * \param fmt A string used as format to initialize the OFMutableString
 * \return A new autoreleased OFMutableString
 */
+ stringWithFormat: (OFString*)fmt, ...;

/**
 * Creates a new OFMutableString from a format C string.
 * See printf for the format syntax.
 *
 * \param fmt A string used as format to initialize the OFMutableString
 * \param args The arguments used in the format string
 * \return A new autoreleased OFMutableString
 */
+ stringWithFormat: (OFString*)fmt
      andArguments: (va_list)args;

/**
 * Initializes an already allocated OFString.
 *
 * \return An initialized OFString
 */
- init;





























/**
 * \return The OFString as a C string
 */
- (const char*)cString;

/**
 * \return The length of the OFString







>
>














>








|







|








|
















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







11
12
13
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
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

#include <stdio.h>
#include <stdarg.h>

#import "OFObject.h"
#import "OFArray.h"

extern int of_string_check_utf8(const char *str, size_t len);

/**
 * A class for managing strings.
 */
@interface OFString: OFObject <OFCopying>
{
	char	     *string;
#ifdef __objc_INCLUDE_GNU
	unsigned int length;
#else
	int	     length;
#if __LP64__
	int	     _unused;
#endif
#endif
	BOOL	     is_utf8;
}

/**
 * \return A new autoreleased OFMutableString
 */
+ string;

/**
 * Creates a new OFString from a C string.
 *
 * \param str A C string to initialize the OFMutableString with
 * \return A new autoreleased OFMutableString
 */
+ stringWithCString: (const char*)str;

/**
 * Creates a new OFString from a format C string.
 * See printf for the format syntax.
 *
 * \param fmt A string used as format to initialize the OFMutableString
 * \return A new autoreleased OFMutableString
 */
+ stringWithFormat: (OFString*)fmt, ...;

/**
 * Creates a new OFString from a format C string.
 * See printf for the format syntax.
 *
 * \param fmt A string used as format to initialize the OFMutableString
 * \param args The arguments used in the format string
 * \return A new autoreleased OFMutableString
 */
+ stringWithFormat: (OFString*)fmt
      andArguments: (va_list)args;

/**
 * Initializes an already allocated OFString.
 *
 * \return An initialized OFString
 */
- init;

/**
 * Initializes an already allocated OFMutableString from a C string.
 *
 * \param str A C string to initialize the OFMutableString with
 * \return An initialized OFMutableString
 */
- initWithCString: (const char*)str;

/**
 * Initializes an already allocated OFMutableString from a format C string.
 * See printf for the format syntax.
 *
 * \param fmt A string used as format to initialize the OFMutableString
 * \return An initialized OFMutableString
 */
- initWithFormat: (OFString*)fmt, ...;

/**
 * Initializes an already allocated OFMutableString from a format C string.
 * See printf for the format syntax.
 *
 * \param fmt A string used as format to initialize the OFMutableString
 * \param args The arguments used in the format string
 * \return An initialized OFMutableString
 */
- initWithFormat: (OFString*)fmt
    andArguments: (va_list)args;

/**
 * \return The OFString as a C string
 */
- (const char*)cString;

/**
 * \return The length of the OFString
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
- (int)compare: (id)obj;

/**
 * Sets the OFString to the specified OFString.
 *
 * \param str An OFString to set the OFString to.
 */
- setTo: (const char*)str;

/**
 * Appends another OFString to the OFString.
 *
 * \param str An OFString to append
 */
- append: (OFString*)str;







|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
- (int)compare: (id)obj;

/**
 * Sets the OFString to the specified OFString.
 *
 * \param str An OFString to set the OFString to.
 */
- setToCString: (const char*)str;

/**
 * Appends another OFString to the OFString.
 *
 * \param str An OFString to append
 */
- append: (OFString*)str;

Modified src/OFString.m from [1c15b5afa3] to [b1b2906cfa].

1
2
3
4
5
6
7
8
9
10
11
12
13

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
56
57
58
59
60
61
62
63
64
65




























































































66
67
68
69
70
71
72
/*
 * Copyright (c) 2008 - 2009
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of libobjfw. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "config.h"


#include <stdarg.h>
#include <stdlib.h>
#include <string.h>







#import "OFString.h"
#import "OFAutoreleasePool.h"
#import "OFURLEncoding.h"
#import "OFExceptions.h"
#import "OFMacros.h"





/* Reference for static linking */
void _reference_to_OFURLEncoding_in_OFString()
{
	_OFURLEncoding_reference = 1;
};





































































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

+ stringWithCString: (const char*)str
{
	return [[[OFMutableString alloc] initWithCString: str] autorelease];
}

+ stringWithFormat: (OFString*)fmt, ...
{
	id ret;
	va_list args;

	va_start(args, fmt);
	ret = [[[OFMutableString alloc] initWithFormat: fmt
					  andArguments: args] autorelease];
	va_end(args);

	return ret;
}

+ stringWithFormat: (OFString*)fmt
      andArguments: (va_list)args
{
	return [[[OFMutableString alloc] initWithFormat: fmt
					   andArguments: args] autorelease];
}

- init
{
	[super init];

	string = NULL;





























































































	return self;
}

- (const char*)cString
{
	return string;













>



>
>
>
>
>
>







>
>
>
>






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



|




|








|
|








|
|







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







1
2
3
4
5
6
7
8
9
10
11
12
13
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
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
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
/*
 * Copyright (c) 2008 - 2009
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of libobjfw. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "config.h"

#define _GNU_SOURCE
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#else
#define madvise(addr, len, advise)
#endif

#import "OFString.h"
#import "OFAutoreleasePool.h"
#import "OFURLEncoding.h"
#import "OFExceptions.h"
#import "OFMacros.h"

#ifndef HAVE_ASPRINTF
#import "asprintf.h"
#endif

/* Reference for static linking */
void _reference_to_OFURLEncoding_in_OFString()
{
	_OFURLEncoding_reference = 1;
};

int
of_string_check_utf8(const char *str, size_t len)
{
	size_t i;
	int utf8 = 0;

	madvise((void*)str, len, MADV_SEQUENTIAL);

	for (i = 0; i < len; i++) {
		/* No sign of UTF-8 here */
		if (OF_LIKELY(!(str[i] & 0x80)))
			continue;

		utf8 = 1;

		/* We're missing a start byte here */
		if (OF_UNLIKELY(!(str[i] & 0x40))) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		/* We have at minimum a 2 byte character -> check next byte */
		if (OF_UNLIKELY(len < i + 1 || (str[i + 1] & 0xC0) != 0x80)) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		/* Check if we have at minimum a 3 byte character */
		if (OF_LIKELY(!(str[i] & 0x20))) {
			i++;
			continue;
		}

		/* We have at minimum a 3 byte char -> check second next byte */
		if (OF_UNLIKELY(len < i + 2 || (str[i + 2] & 0xC0) != 0x80)) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		/* Check if we have a 4 byte character */
		if (OF_LIKELY(!(str[i] & 0x10))) {
			i += 2;
			continue;
		}

		/* We have a 4 byte character -> check third next byte */
		if (OF_UNLIKELY(len < i + 3 || (str[i + 3] & 0xC0) != 0x80)) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		/*
		 * Just in case, check if there's a 5th character, which is
		 * forbidden by UTF-8
		 */
		if (OF_UNLIKELY(str[i] & 0x08)) {
			madvise((void*)str, len, MADV_NORMAL);
			return -1;
		}

		i += 3;
	}

	madvise((void*)str, len, MADV_NORMAL);

	return utf8;
}

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

+ stringWithCString: (const char*)str
{
	return [[[self alloc] initWithCString: str] autorelease];
}

+ stringWithFormat: (OFString*)fmt, ...
{
	id ret;
	va_list args;

	va_start(args, fmt);
	ret = [[[self alloc] initWithFormat: fmt
			       andArguments: args] autorelease];
	va_end(args);

	return ret;
}

+ stringWithFormat: (OFString*)fmt
      andArguments: (va_list)args
{
	return [[[self alloc] initWithFormat: fmt
				andArguments: args] autorelease];
}

- init
{
	[super init];

	string = NULL;

	return self;
}

- initWithCString: (const char*)str
{
	Class c;

	self = [super init];

	if (str != NULL) {
		length = strlen(str);

		switch (of_string_check_utf8(str, length)) {
			case 1:
				is_utf8 = YES;
				break;
			case -1:
				c = isa;
				[super dealloc];
				@throw [OFInvalidEncodingException
					newWithClass: c];
		}

		@try {
			string = [self allocWithSize: length + 1];
		} @catch (OFException *e) {
			/*
			 * We can't use [super dealloc] on OS X here.
			 * Compiler bug? Anyway, [self dealloc] will do here as
			 * we don't reimplement dealloc.
			 */
			[self dealloc];
			@throw e;
		}
		memcpy(string, str, length + 1);
	}

	return self;
}

- initWithFormat: (OFString*)fmt, ...
{
	id ret;
	va_list args;

	va_start(args, fmt);
	ret = [self initWithFormat: fmt
		      andArguments: args];
	va_end(args);

	return ret;
}

- initWithFormat: (OFString*)fmt
    andArguments: (va_list)args
{
	int t;
	Class c;

	self = [super init];

	if (fmt == NULL) {
		c = isa;
		[super dealloc];
		@throw [OFInvalidFormatException newWithClass: c];
	}

	if ((t = vasprintf(&string, [fmt cString], args)) == -1) {
		c = isa;
		[super dealloc];
		@throw [OFInitializationFailedException newWithClass: c];
	}
	length = t;

	switch (of_string_check_utf8(string, length)) {
		case 1:
			is_utf8 = YES;
			break;
		case -1:
			free(string);
			c = isa;
			[super dealloc];
			@throw [OFInvalidEncodingException newWithClass: c];
	}

	@try {
		[self addToMemoryPool: string];
	} @catch (OFException *e) {
		free(string);
		@throw e;
	}

	return self;
}

- (const char*)cString
{
	return string;
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
	for (i = 0; i < length; i++)
		OF_HASH_ADD(hash, string[i]);
	OF_HASH_FINALIZE(hash);

	return hash;
}

- setTo: (const char*)str
{
	@throw [OFNotImplementedException newWithClass: isa
					   andSelector: _cmd];
}

- append: (OFString*)str
{







|







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
	for (i = 0; i < length; i++)
		OF_HASH_ADD(hash, string[i]);
	OF_HASH_FINALIZE(hash);

	return hash;
}

- setToCString: (const char*)str
{
	@throw [OFNotImplementedException newWithClass: isa
					   andSelector: _cmd];
}

- append: (OFString*)str
{

Modified tests/OFString/OFString.m from [1bae449326] to [203f97552a].

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
int
main()
{
	size_t i = 0;
	size_t j = 0;

	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFString *s1 = [OFString stringWithCString: "test"];
	OFString *s2 = [OFString stringWithCString: ""];
	OFString *s3;
	OFString *s4 = [OFString string];
	OFArray *a;

	s3 = [s1 copy];

	CHECK([s1 isEqual: s3])
	CHECK(![s1 isEqual: [[OFObject alloc] init]])
	CHECK([s1 hash] == [s3 hash])

	[s2 appendCString: "12"];
	[s2 append: @"3"];
	[s4 setTo: [s2 cString]];

	CHECK(![s2 compare: s4])
	CHECK(!strcmp([[s1 append: s2] cString], "test123"))
	CHECK([s1 hash] == 0xC44F49A4)
	CHECK(strlen([s1 cString]) == [s1 length] && [s1 length] == 7)
	CHECK(!strcmp([[s1 reverse] cString], "321tset"))
	CHECK(!strcmp([[s1 upper] cString], "321TSET"))
	CHECK(!strcmp([[s1 lower] cString], "321tset"))

	/* Also clears all the memory of the returned C strings */
	[pool release];

	/* UTF-8 tests */
	CHECK_EXCEPT(s1 = [OFString stringWithCString: "\xE0\x80"],
	    OFInvalidEncodingException)
	CHECK_EXCEPT(s1 = [OFString stringWithCString: "\xF0\x80\x80\xC0"],
	    OFInvalidEncodingException)

	s1 = [OFString stringWithCString: "äöü€𝄞"];
	CHECK(!strcmp([[s1 reverse] cString], "𝄞€üöä"))
	[s1 dealloc];

	/* Format tests */
	s1 = [OFString stringWithFormat: @"%s: %d", "test", 123];
	CHECK(!strcmp([s1 cString], "test: 123"))

	[s1 appendWithFormat: @"%02X", 15];
	CHECK(!strcmp([s1 cString], "test: 1230F"))

	a = [@"fooXXbarXXXXbazXXXX" splitWithDelimiter: @"XX"];
	CHECK([[a object: j++] isEqual: @"foo"])







|
|

|










|


















|




|







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
int
main()
{
	size_t i = 0;
	size_t j = 0;

	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFString *s1 = [OFMutableString stringWithCString: "test"];
	OFString *s2 = [OFMutableString stringWithCString: ""];
	OFString *s3;
	OFString *s4 = [OFMutableString string];
	OFArray *a;

	s3 = [s1 copy];

	CHECK([s1 isEqual: s3])
	CHECK(![s1 isEqual: [[OFObject alloc] init]])
	CHECK([s1 hash] == [s3 hash])

	[s2 appendCString: "12"];
	[s2 append: @"3"];
	[s4 setToCString: [s2 cString]];

	CHECK(![s2 compare: s4])
	CHECK(!strcmp([[s1 append: s2] cString], "test123"))
	CHECK([s1 hash] == 0xC44F49A4)
	CHECK(strlen([s1 cString]) == [s1 length] && [s1 length] == 7)
	CHECK(!strcmp([[s1 reverse] cString], "321tset"))
	CHECK(!strcmp([[s1 upper] cString], "321TSET"))
	CHECK(!strcmp([[s1 lower] cString], "321tset"))

	/* Also clears all the memory of the returned C strings */
	[pool release];

	/* UTF-8 tests */
	CHECK_EXCEPT(s1 = [OFString stringWithCString: "\xE0\x80"],
	    OFInvalidEncodingException)
	CHECK_EXCEPT(s1 = [OFString stringWithCString: "\xF0\x80\x80\xC0"],
	    OFInvalidEncodingException)

	s1 = [OFMutableString stringWithCString: "äöü€𝄞"];
	CHECK(!strcmp([[s1 reverse] cString], "𝄞€üöä"))
	[s1 dealloc];

	/* Format tests */
	s1 = [OFMutableString stringWithFormat: @"%s: %d", "test", 123];
	CHECK(!strcmp([s1 cString], "test: 123"))

	[s1 appendWithFormat: @"%02X", 15];
	CHECK(!strcmp([s1 cString], "test: 1230F"))

	a = [@"fooXXbarXXXXbazXXXX" splitWithDelimiter: @"XX"];
	CHECK([[a object: j++] isEqual: @"foo"])