ObjFW  Check-in [b519963535]

Overview
Comment:Path handling for Nintendo 3DS
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: b5199635357180395fbfd80406affd2772d9dccd5837411f687f89de84b8b650
User & Date: js on 2018-08-18 23:10:40
Other Links: manifest | tags
Context
2018-08-19
01:04
Do not use lstat() on Nintendo 3DS check-in: c162213e4a user: js tags: trunk
2018-08-18
23:10
Path handling for Nintendo 3DS check-in: b519963535 user: js tags: trunk
17:01
OFDNSResolver: Obtain name servers on AmigaOS 4 check-in: 3d67a890fb user: js tags: trunk
Changes

Modified src/OFString+PathAdditions.m from [f88a76c9e5] to [3ae7057f01].

19
20
21
22
23
24
25


26
27
28

#import "platform.h"

#if defined(OF_WINDOWS) || defined(OF_MSDOS)
# import "OFString+PathAdditions_DOS.m"
#elif defined(OF_AMIGAOS)
# import "OFString+PathAdditions_AmigaOS.m"


#else
# import "OFString+PathAdditions_UNIX.m"
#endif







>
>



19
20
21
22
23
24
25
26
27
28
29
30

#import "platform.h"

#if defined(OF_WINDOWS) || defined(OF_MSDOS)
# import "OFString+PathAdditions_DOS.m"
#elif defined(OF_AMIGAOS)
# import "OFString+PathAdditions_AmigaOS.m"
#elif defined(OF_NINTENDO_3DS)
# import "OFString+PathAdditions_3DS.m"
#else
# import "OFString+PathAdditions_UNIX.m"
#endif

Added src/OFString+PathAdditions_3DS.m version [f97635b389].





























































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
 *               2018
 *   Jonathan Schleifer <js@heap.zone>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFString+PathAdditions.h"
#import "OFArray.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components
{
	OFMutableString *ret = [OFMutableString string];
	void *pool = objc_autoreleasePoolPush();
	bool first = true;

	for (OFString *component in components) {
		if ([component length] == 0)
			continue;

		if ([component isEqual: @"/"])
			continue;

		if (!first && ![ret hasSuffix: @"/"])
			[ret appendString: @"/"];

		[ret appendString: component];

		first = false;
	}

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)isAbsolutePath
{
	return [self containsString: @":"];
}

- (OFArray *)pathComponents
{
	OFMutableArray OF_GENERIC(OFString *) *ret = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();
	const char *cString = [self UTF8String];
	size_t i, last = 0, pathCStringLength = [self UTF8StringLength];

	if (pathCStringLength == 0) {
		objc_autoreleasePoolPop(pool);
		return ret;
	}

	for (i = 0; i < pathCStringLength; i++) {
		if (cString[i] == '/') {
			if (i - last != 0)
				[ret addObject: [OFString
				    stringWithUTF8String: cString + last
						  length: i - last]];

			last = i + 1;
		}
	}
	if (i - last != 0)
		[ret addObject: [OFString stringWithUTF8String: cString + last
							length: i - last]];

	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (OFString *)lastPathComponent
{
	void *pool = objc_autoreleasePoolPush();
	const char *cString = [self UTF8String];
	size_t pathCStringLength = [self UTF8StringLength];
	ssize_t i;
	OFString *ret;

	if (pathCStringLength == 0) {
		objc_autoreleasePoolPop(pool);
		return @"";
	}

	if (cString[pathCStringLength - 1] == '/')
		pathCStringLength--;

	if (pathCStringLength == 0) {
		objc_autoreleasePoolPop(pool);
		return @"";
	}

	if (pathCStringLength - 1 > SSIZE_MAX)
		@throw [OFOutOfRangeException exception];

	for (i = pathCStringLength - 1; i >= 0; i--) {
		if (cString[i] == '/') {
			i++;
			break;
		}
	}

	/*
	 * Only one component, but the trailing delimiter might have been
	 * removed, so return a new string anyway.
	 */
	if (i < 0)
		i = 0;

	ret = [[OFString alloc] initWithUTF8String: cString + i
					    length: pathCStringLength - i];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)pathExtension
{
	void *pool = objc_autoreleasePoolPush();
	OFString *ret, *fileName;
	size_t pos;

	fileName = [self lastPathComponent];
	pos = [fileName rangeOfString: @"."
			      options: OF_STRING_SEARCH_BACKWARDS].location;
	if (pos == OF_NOT_FOUND || pos == 0) {
		objc_autoreleasePoolPop(pool);
		return @"";
	}

	ret = [fileName substringWithRange:
	    of_range(pos + 1, [fileName length] - pos - 1)];

	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}

- (OFString *)stringByDeletingLastPathComponent
{
	void *pool = objc_autoreleasePoolPush();
	const char *cString = [self UTF8String];
	size_t pathCStringLength = [self UTF8StringLength];
	OFString *ret;

	if (pathCStringLength == 0) {
		objc_autoreleasePoolPop(pool);
		return @"";
	}

	if (cString[pathCStringLength - 1] == '/')
		pathCStringLength--;

	if (pathCStringLength == 0) {
		objc_autoreleasePoolPop(pool);
		return @"";
	}

	for (size_t i = pathCStringLength; i >= 1; i--) {
		if (cString[i - 1] == '/') {
			ret = [[OFString alloc] initWithUTF8String: cString
							    length: i - 1];

			objc_autoreleasePoolPop(pool);

			return [ret autorelease];
		}
	}

	objc_autoreleasePoolPop(pool);

	return @".";
}

- (OFString *)stringByDeletingPathExtension
{
	void *pool;
	OFMutableArray OF_GENERIC(OFString *) *components;
	OFString *ret, *fileName;
	size_t pos;

	if ([self length] == 0)
		return [[self copy] autorelease];

	pool = objc_autoreleasePoolPush();
	components = [[[self pathComponents] mutableCopy] autorelease];
	fileName = [components lastObject];

	pos = [fileName rangeOfString: @"."
			      options: OF_STRING_SEARCH_BACKWARDS].location;
	if (pos == OF_NOT_FOUND || pos == 0) {
		objc_autoreleasePoolPop(pool);
		return [[self copy] autorelease];
	}

	fileName = [fileName substringWithRange: of_range(0, pos)];
	[components replaceObjectAtIndex: [components count] - 1
			      withObject: fileName];

	ret = [OFString pathWithComponents: components];

	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}

- (OFString *)stringByStandardizingPath
{
	void *pool = objc_autoreleasePoolPush();
	OFArray OF_GENERIC(OFString *) *components;
	OFMutableArray OF_GENERIC(OFString *) *array;
	OFString *ret;
	bool done = false;

	if ([self length] == 0)
		return @"";

	components = [self pathComponents];

	if ([components count] == 1) {
		objc_autoreleasePoolPop(pool);
		return [[self copy] autorelease];
	}

	array = [[components mutableCopy] autorelease];

	while (!done) {
		size_t length = [array count];

		done = true;

		for (size_t i = 0; i < length; i++) {
			OFString *component = [array objectAtIndex: i];
			OFString *parent =
			    (i > 0 ? [array objectAtIndex: i - 1] : 0);

			if ([component isEqual: @"."] ||
			   [component length] == 0) {
				[array removeObjectAtIndex: i];

				done = false;
				break;
			}

			if ([component isEqual: @".."] &&
			    parent != nil && ![parent isEqual: @".."]) {
				[array removeObjectsInRange:
				    of_range(i - 1, 2)];

				done = false;
				break;
			}
		}
	}

	if ([self hasSuffix: @"/"])
		[array addObject: @""];

	ret = [[array componentsJoinedByString: @"/"] retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{
	if ([self hasSuffix: @"/"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"/"];
		[ret appendString: component];

		[ret makeImmutable];

		return ret;
	}
}
@end

Modified src/OFURL.m from [f9c0df659c] to [3dd9d958c3].

86
87
88
89
90
91
92


93
94
95
96
97
98
99
			[ret appendString: component];
		}
	}

	[ret makeImmutable];

	return ret;


# else
	return path;
# endif
}

static OFString *
URLPathToPath(OFString *path)







>
>







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
			[ret appendString: component];
		}
	}

	[ret makeImmutable];

	return ret;
# elif defined(OF_NINTENDO_3DS)
	return [path stringByPrependingString: @"/"];
# else
	return path;
# endif
}

static OFString *
URLPathToPath(OFString *path)
126
127
128
129
130
131
132


133
134
135
136
137
138
139

		if ([component isEqual: @".."])
			[components replaceObjectAtIndex: i
					      withObject: @"/"];
	}

	return [OFString pathWithComponents: components];


# else
	return path;
# endif
}
#endif

@interface OFCharacterSet_invertedSetWithPercent: OFCharacterSet







>
>







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

		if ([component isEqual: @".."])
			[components replaceObjectAtIndex: i
					      withObject: @"/"];
	}

	return [OFString pathWithComponents: components];
# elif defined(OF_NINTENDO_3DS)
	return [path substringWithRange: of_range(1, [path length] - 1)];
# else
	return path;
# endif
}
#endif

@interface OFCharacterSet_invertedSetWithPercent: OFCharacterSet