ObjFW  Check-in [eba3667137]

Overview
Comment:Add -[OFURL lastPathComponent]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: eba36671376121afc2d09bb7db36ee227741fd6100f62190eee09eb76748d204
User & Date: js on 2017-10-29 15:05:07
Other Links: manifest | tags
Context
2017-10-29
15:23
OFURL: Properties store unencoded strings now check-in: c1c9443c1a user: js tags: trunk
15:05
Add -[OFURL lastPathComponent] check-in: eba3667137 user: js tags: trunk
13:37
Add -[OFURL pathComponents] check-in: 7f64141183 user: js tags: trunk
Changes

Modified src/OFMutableURL.h from [4ea68f1b3c] to [db8fdd5d15].

50
51
52
53
54
55
56








57
58
59
60
61
62
63
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *password;

/*!
 * The path part of the URL.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *path;









/*!
 * The parameters part of the URL.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *parameters;

/*!







>
>
>
>
>
>
>
>







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *password;

/*!
 * The path part of the URL.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *path;

/*!
 * The path of the URL split into components.
 *
 * The first component must always be empty to designate the root.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFArray OF_GENERIC(OFString *) *pathComponents;

/*!
 * The parameters part of the URL.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *parameters;

/*!
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*!
 * @brief Initializes an already allocated OFMutableURL.
 *
 * @return An initialized OFMutableURL
 */
- (instancetype)init;

/*!
 * @brief Sets the URL's path from the specified path components.
 *
 * The first component must always be empty to designate the root.
 *
 * @param components The path components to set the URL's path from
 */
- (void)setPathComponents:
    (nullable OFArray OF_GENERIC(OFString *) *)components;

/*!
 * @brief Converts the mutable URL to an immutable URL.
 */
- (void)makeImmutable;
@end

OF_ASSUME_NONNULL_END







<
<
<
<
<
<
<
<
<
<







88
89
90
91
92
93
94










95
96
97
98
99
100
101
/*!
 * @brief Initializes an already allocated OFMutableURL.
 *
 * @return An initialized OFMutableURL
 */
- (instancetype)init;











/*!
 * @brief Converts the mutable URL to an immutable URL.
 */
- (void)makeImmutable;
@end

OF_ASSUME_NONNULL_END

Modified src/OFMutableURL.m from [5d3d519f50] to [6d9eb70d6a].

21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
#import "OFNumber.h"
#import "OFString.h"
#import "OFURL+Private.h"

#import "OFInvalidFormatException.h"

@implementation OFMutableURL
@dynamic scheme, host, port, user, password, path, parameters, query, fragment;


+ (instancetype)URL
{
	return [[[self alloc] init] autorelease];
}

- (instancetype)init







|
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "OFNumber.h"
#import "OFString.h"
#import "OFURL+Private.h"

#import "OFInvalidFormatException.h"

@implementation OFMutableURL
@dynamic scheme, host, port, user, password, path, pathComponents, parameters;
@dynamic query, fragment;

+ (instancetype)URL
{
	return [[[self alloc] init] autorelease];
}

- (instancetype)init
74
75
76
77
78
79
80




















81
82
83
84
85
86
87

- (void)setPath: (OFString *)path
{
	OFString *old = _path;
	_path = [path copy];
	[old release];
}





















- (void)setParameters: (OFString *)parameters
{
	OFString *old = _parameters;
	_parameters = [parameters copy];
	[old release];
}







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







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

- (void)setPath: (OFString *)path
{
	OFString *old = _path;
	_path = [path copy];
	[old release];
}

- (void)setPathComponents: (OFArray *)components
{
	void *pool = objc_autoreleasePoolPush();

	if (components == nil) {
		[self setPath: nil];
		return;
	}

	if ([components count] == 0)
		@throw [OFInvalidFormatException exception];

	if ([[components firstObject] length] != 0)
		@throw [OFInvalidFormatException exception];

	[self setPath: [components componentsJoinedByString: @"/"]];

	objc_autoreleasePoolPop(pool);
}

- (void)setParameters: (OFString *)parameters
{
	OFString *old = _parameters;
	_parameters = [parameters copy];
	[old release];
}
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
- (void)setFragment: (OFString *)fragment
{
	OFString *old = _fragment;
	_fragment = [fragment copy];
	[old release];
}

- (void)setPathComponents: (OFArray *)components
{
	void *pool = objc_autoreleasePoolPush();

	if (components == nil) {
		[self setPath: nil];
		return;
	}

	if ([components count] == 0)
		@throw [OFInvalidFormatException exception];

	if ([[components firstObject] length] != 0)
		@throw [OFInvalidFormatException exception];

	[self setPath: [components componentsJoinedByString: @"/"]];

	objc_autoreleasePoolPop(pool);
}

- (id)copy
{
	OFMutableURL *copy = [self mutableCopy];

	[copy makeImmutable];

	return copy;







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







117
118
119
120
121
122
123




















124
125
126
127
128
129
130
- (void)setFragment: (OFString *)fragment
{
	OFString *old = _fragment;
	_fragment = [fragment copy];
	[old release];
}





















- (id)copy
{
	OFMutableURL *copy = [self mutableCopy];

	[copy makeImmutable];

	return copy;

Modified src/OFURL.h from [9597f5d99f] to [6ad21dffff].

63
64
65
66
67
68
69
















70
71
72
73
74
75
76
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *password;

/*!
 * The path part of the URL.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *path;

















/*!
 * The parameters part of the URL.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *parameters;

/*!
 * The query part of the URL.







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







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
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *password;

/*!
 * The path part of the URL.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *path;

/*!
 * The path of the URL split into components.
 *
 * The first component must always be empty to designate the root.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFArray OF_GENERIC(OFString *) *pathComponents;

/*!
 * The last path component of the URL.
 *
 * Returns the empty string if the path is the root.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *lastPathComponent;

/*!
 * The parameters part of the URL.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *parameters;

/*!
 * The query part of the URL.
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*!
 * @brief Returns the URL as a string.
 *
 * @return The URL as a string
 */
- (OFString *)string;

/*!
 * @brief Returns the path of the URL split into components.
 *
 * The first component is always empty to designate the root.
 *
 * @return The path of the URL split into components
 */
- (nullable OFArray OF_GENERIC(OFString *) *)pathComponents;

/*!
 * @brief Returns the local file system representation for a file URL.
 *
 * This only exists for URLs with the file scheme and throws an exception
 * otherwise.
 *
 * @return The local file system representation for a file URL







<
<
<
<
<
<
<
<
<







191
192
193
194
195
196
197









198
199
200
201
202
203
204
/*!
 * @brief Returns the URL as a string.
 *
 * @return The URL as a string
 */
- (OFString *)string;










/*!
 * @brief Returns the local file system representation for a file URL.
 *
 * This only exists for URLs with the file scheme and throws an exception
 * otherwise.
 *
 * @return The local file system representation for a file URL

Modified src/OFURL.m from [c329b07d23] to [4e9f7c9f9a].

436
437
438
439
440
441
442













































443
444
445
446
447
448
449
	return _password;
}

- (OFString *)path
{
	return _path;
}














































- (OFString *)parameters
{
	return _parameters;
}

- (OFString *)query







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







436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
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
494
	return _password;
}

- (OFString *)path
{
	return _path;
}

- (OFArray *)pathComponents
{
	return [_path componentsSeparatedByString: @"/"];
}

- (OFString *)lastPathComponent
{
	void *pool;
	OFString *path;
	const char *UTF8String, *lastComponent;
	size_t length;
	OFString *ret;

	if (_path == nil)
		return nil;

	if ([_path isEqual: @"/"])
		return @"";

	pool = objc_autoreleasePoolPush();
	path = _path;

	if ([path hasSuffix: @"/"])
		path = [path substringWithRange:
		    of_range(0, [path length] - 1)];

	UTF8String = lastComponent = [path UTF8String];
	length = [path UTF8StringLength];

	for (size_t i = 1; i <= length; i++) {
		if (UTF8String[length - i] == '/') {
			lastComponent = UTF8String + (length - i) + 1;
			break;
		}
	}

	ret = [[OFString alloc]
	    initWithUTF8String: lastComponent
			length: length - (lastComponent - UTF8String)];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)parameters
{
	return _parameters;
}

- (OFString *)query
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
	objc_autoreleasePoolPop(pool);

	[ret makeImmutable];

	return ret;
}

- (OFArray *)pathComponents
{
	return [_path componentsSeparatedByString: @"/"];
}

- (OFString *)fileSystemRepresentation
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

	if (![_scheme isEqual: @"file"])
		@throw [OFInvalidArgumentException exception];

	if (![_path hasPrefix: @"/"])
		@throw [OFInvalidFormatException exception];

	path = [[_path copy] autorelease];

	if ([path hasSuffix: @"/"])
		path = [path substringWithRange:
		    of_range(0, [path length] - 1)];

#ifndef OF_PATH_STARTS_WITH_SLASH
	path = [path substringWithRange: of_range(1, [path length] - 1)];







<
<
<
<
<











|







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
589
	objc_autoreleasePoolPop(pool);

	[ret makeImmutable];

	return ret;
}






- (OFString *)fileSystemRepresentation
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

	if (![_scheme isEqual: @"file"])
		@throw [OFInvalidArgumentException exception];

	if (![_path hasPrefix: @"/"])
		@throw [OFInvalidFormatException exception];

	path = _path;

	if ([path hasSuffix: @"/"])
		path = [path substringWithRange:
		    of_range(0, [path length] - 1)];

#ifndef OF_PATH_STARTS_WITH_SLASH
	path = [path substringWithRange: of_range(1, [path length] - 1)];

Modified tests/OFURLTests.m from [0dd131c155] to [fc4f5147c7].

13
14
15
16
17
18
19

20
21
22
23
24
25
26
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFURL.h"

#ifdef OF_HAVE_FILES
# import "OFFileManager.h"
#endif
#import "OFNumber.h"
#import "OFString.h"
#import "OFAutoreleasePool.h"








>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFURL.h"
#import "OFArray.h"
#ifdef OF_HAVE_FILES
# import "OFFileManager.h"
#endif
#import "OFNumber.h"
#import "OFString.h"
#import "OFAutoreleasePool.h"

77
78
79
80
81
82
83














84
85
86
87
88
89
90
	TEST(@"-[password]",
	    [[u1 password] isEqual: @"p%40w"] && [u4 password] == nil)
	TEST(@"-[host]", [[u1 host] isEqual: @"ho%3Ast"] && [u4 port] == 0)
	TEST(@"-[port]", [[u1 port] isEqual: [OFNumber numberWithUInt16: 1234]])
	TEST(@"-[path]",
	    [[u1 path] isEqual: @"/pa%3Bth"] &&
	    [[u4 path] isEqual: @"/etc/passwd"])














	TEST(@"-[parameters]",
	    [[u1 parameters] isEqual: @"pa%3Fram"] && [u4 parameters] == nil)
	TEST(@"-[query]",
	    [[u1 query] isEqual: @"que%23ry"] && [u4 query] == nil)
	TEST(@"-[fragment]",
	    [[u1 fragment] isEqual: @"frag%23ment"] && [u4 fragment] == nil)








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







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
	TEST(@"-[password]",
	    [[u1 password] isEqual: @"p%40w"] && [u4 password] == nil)
	TEST(@"-[host]", [[u1 host] isEqual: @"ho%3Ast"] && [u4 port] == 0)
	TEST(@"-[port]", [[u1 port] isEqual: [OFNumber numberWithUInt16: 1234]])
	TEST(@"-[path]",
	    [[u1 path] isEqual: @"/pa%3Bth"] &&
	    [[u4 path] isEqual: @"/etc/passwd"])
	TEST(@"-[pathComponents]",
	    [[u1 pathComponents] isEqual:
	    [OFArray arrayWithObjects: @"", @"pa%3Bth", nil]] &&
	    [[u4 pathComponents] isEqual:
	    [OFArray arrayWithObjects: @"", @"etc", @"passwd", nil]])
	TEST(@"-[lastPathComponent",
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz/"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo/"]
	    lastPathComponent] isEqual: @"foo"] &&
	    [[[OFURL URLWithString: @"http://host/"]
	    lastPathComponent] isEqual: @""])
	TEST(@"-[parameters]",
	    [[u1 parameters] isEqual: @"pa%3Fram"] && [u4 parameters] == nil)
	TEST(@"-[query]",
	    [[u1 query] isEqual: @"que%23ry"] && [u4 query] == nil)
	TEST(@"-[fragment]",
	    [[u1 fragment] isEqual: @"frag%23ment"] && [u4 fragment] == nil)