Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -692,10 +692,16 @@ 4B3D23EE1337FFD000DD29B8 /* of_asprintf.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB50DD012F863C700C9393F /* of_asprintf.m */; }; 4B3D5694139A617D0010A78F /* OFSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B3D5693139A617D0010A78F /* OFSerializationTests.m */; }; 4B3ED7C21AF62C30004C8FF1 /* OFGetOptionFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3ED7C01AF62C30004C8FF1 /* OFGetOptionFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B3ED7C31AF62C30004C8FF1 /* OFGetOptionFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B3ED7C11AF62C30004C8FF1 /* OFGetOptionFailedException.m */; }; 4B40EC1B189FE2650031E19E /* socket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B40EC1A189FE2650031E19E /* socket.m */; }; + 4B4116D01F21654200E78916 /* OFMutableURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4116CD1F21654200E78916 /* OFMutableURL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B4116D11F21654200E78916 /* OFMutableURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4116CD1F21654200E78916 /* OFMutableURL.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B4116D21F21654200E78916 /* OFMutableURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B4116CE1F21654200E78916 /* OFMutableURL.m */; }; + 4B4116D31F21654200E78916 /* OFMutableURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B4116CE1F21654200E78916 /* OFMutableURL.m */; }; + 4B4116D41F21654200E78916 /* OFURL+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4116CF1F21654200E78916 /* OFURL+Private.h */; }; + 4B4116D51F21654200E78916 /* OFURL+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4116CF1F21654200E78916 /* OFURL+Private.h */; }; 4B44836D1D0497DE005D12A7 /* OFUndefinedKeyException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B44836B1D0497DE005D12A7 /* OFUndefinedKeyException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B44836E1D0497DE005D12A7 /* OFUndefinedKeyException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B44836C1D0497DE005D12A7 /* OFUndefinedKeyException.m */; }; 4B4483711D04989C005D12A7 /* RuntimeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B44836F1D049887005D12A7 /* RuntimeTests.m */; }; 4B45355313DCFE1E0037AB4D /* OFCountedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B45355113DCFE1E0037AB4D /* OFCountedSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B45355413DCFE1E0037AB4D /* OFCountedSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B45355213DCFE1E0037AB4D /* OFCountedSet.m */; }; @@ -1310,10 +1316,13 @@ 4B3D23BB1337FC5800DD29B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = misc/Info.plist; sourceTree = SOURCE_ROOT; }; 4B3D5693139A617D0010A78F /* OFSerializationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSerializationTests.m; path = tests/OFSerializationTests.m; sourceTree = ""; }; 4B3ED7C01AF62C30004C8FF1 /* OFGetOptionFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFGetOptionFailedException.h; path = src/exceptions/OFGetOptionFailedException.h; sourceTree = ""; }; 4B3ED7C11AF62C30004C8FF1 /* OFGetOptionFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFGetOptionFailedException.m; path = src/exceptions/OFGetOptionFailedException.m; sourceTree = ""; }; 4B40EC1A189FE2650031E19E /* socket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = socket.m; path = src/socket.m; sourceTree = ""; }; + 4B4116CD1F21654200E78916 /* OFMutableURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFMutableURL.h; path = src/OFMutableURL.h; sourceTree = ""; }; + 4B4116CE1F21654200E78916 /* OFMutableURL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFMutableURL.m; path = src/OFMutableURL.m; sourceTree = ""; }; + 4B4116CF1F21654200E78916 /* OFURL+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OFURL+Private.h"; path = "src/OFURL+Private.h"; sourceTree = ""; }; 4B44836B1D0497DE005D12A7 /* OFUndefinedKeyException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFUndefinedKeyException.h; path = src/exceptions/OFUndefinedKeyException.h; sourceTree = ""; }; 4B44836C1D0497DE005D12A7 /* OFUndefinedKeyException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFUndefinedKeyException.m; path = src/exceptions/OFUndefinedKeyException.m; sourceTree = ""; }; 4B44836F1D049887005D12A7 /* RuntimeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RuntimeTests.m; path = tests/RuntimeTests.m; sourceTree = ""; }; 4B45355113DCFE1E0037AB4D /* OFCountedSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCountedSet.h; path = src/OFCountedSet.h; sourceTree = ""; }; 4B45355213DCFE1E0037AB4D /* OFCountedSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCountedSet.m; path = src/OFCountedSet.m; sourceTree = ""; }; @@ -2100,10 +2109,12 @@ 4BA85BC7140ECCE800E91D51 /* OFMutableSet_hashtable.m */, 4B6799731099E7C50041064A /* OFMutableString.h */, 4B6799741099E7C50041064A /* OFMutableString.m */, 4B55254E147AA5DB0003BF47 /* OFMutableString_UTF8.h */, 4B55254F147AA5DB0003BF47 /* OFMutableString_UTF8.m */, + 4B4116CD1F21654200E78916 /* OFMutableURL.h */, + 4B4116CE1F21654200E78916 /* OFMutableURL.m */, 4B6743FA163C395900EB1E59 /* OFMutex.h */, 4B6743FB163C395900EB1E59 /* OFMutex.m */, 4B511B7A139C0A34003764A5 /* OFNull.h */, 4B511B7B139C0A34003764A5 /* OFNull.m */, 4B6799751099E7C50041064A /* OFNumber.h */, @@ -2203,10 +2214,11 @@ 4BA02BA015041F5900002F84 /* OFTLSSocket.h */, 4B7769EF1895ED0C00D12284 /* OFUDPSocket.h */, 4B7769F01895ED0C00D12284 /* OFUDPSocket.m */, 4B4A61F212DF5EA20048F3F2 /* OFURL.h */, 4B4A61F312DF5EA20048F3F2 /* OFURL.m */, + 4B4116CF1F21654200E78916 /* OFURL+Private.h */, 4BF1BCCE11C9663F0025511F /* OFXMLAttribute.h */, 4BF1BCCF11C9663F0025511F /* OFXMLAttribute.m */, 4B49EA67143B3A090005BBC6 /* OFXMLCDATA.h */, 4B49EA68143B3A090005BBC6 /* OFXMLCDATA.m */, 4B49EA69143B3A090005BBC6 /* OFXMLCharacters.h */, @@ -2460,10 +2472,11 @@ 4B2C21FF1DA292BE00735907 /* OFMessagePackRepresentation.h in Headers */, 4B2C22001DA292BE00735907 /* OFMutableArray.h in Headers */, 4B2C22011DA292BE00735907 /* OFMutableDictionary.h in Headers */, 4B2C22021DA292BE00735907 /* OFMutableSet.h in Headers */, 4B2C22031DA292BE00735907 /* OFMutableString.h in Headers */, + 4B4116D11F21654200E78916 /* OFMutableURL.h in Headers */, 4B2C22041DA292BE00735907 /* OFMutex.h in Headers */, 4B2C22051DA292BE00735907 /* OFNull.h in Headers */, 4B2C22061DA292BE00735907 /* OFNumber.h in Headers */, 4B2C22071DA292BE00735907 /* OFObject.h in Headers */, 4B2C22081DA292BE00735907 /* OFObject+KeyValueCoding.h in Headers */, @@ -2626,10 +2639,11 @@ 4B2C22A31DA292BE00735907 /* OFString_UTF8+Private.h in Headers */, 4B2C22A41DA292BE00735907 /* OFTarArchiveEntry+Private.h in Headers */, 4B2C22A51DA292BE00735907 /* OFTCPSocket+SOCKS5.h in Headers */, 4B2C22A61DA292BE00735907 /* OFThread+Private.h in Headers */, 4B2C22A71DA292BE00735907 /* OFTimer+Private.h in Headers */, + 4B4116D51F21654200E78916 /* OFURL+Private.h in Headers */, 4B853CEC1EBFDEB000A4B2C4 /* OFXMLNode+Private.h in Headers */, 4B2C22A81DA292BE00735907 /* OFZIPArchiveEntry+Private.h in Headers */, 4B2C22AA1DA292BE00735907 /* socket_helpers.h in Headers */, 4BCE4EC51ED98D1400502FF0 /* unistd_wrapper.h in Headers */, 4BFC37BE1E50E11C00EE1269 /* common.h in Headers */, @@ -2684,10 +2698,11 @@ 4B879A8E177231F000EBCEA4 /* OFMessagePackRepresentation.h in Headers */, 4B3D23CD1337FCB000DD29B8 /* OFMutableArray.h in Headers */, 4B3D23CE1337FCB000DD29B8 /* OFMutableDictionary.h in Headers */, 4B39844713D3AFB400E6F825 /* OFMutableSet.h in Headers */, 4B3D23CF1337FCB000DD29B8 /* OFMutableString.h in Headers */, + 4B4116D01F21654200E78916 /* OFMutableURL.h in Headers */, 4B674403163C395900EB1E59 /* OFMutex.h in Headers */, 4B511B7C139C0A34003764A5 /* OFNull.h in Headers */, 4B3D23D01337FCB000DD29B8 /* OFNumber.h in Headers */, 4B3D23D11337FCB000DD29B8 /* OFObject.h in Headers */, 4BC176301D04963000C32718 /* OFObject+KeyValueCoding.h in Headers */, @@ -2851,10 +2866,11 @@ 4B6C8ADB17BD5C2E00B194F2 /* OFString_UTF8+Private.h in Headers */, 4BC176361D04963000C32718 /* OFTarArchiveEntry+Private.h in Headers */, 4BD653C5143B8489006182F0 /* OFTCPSocket+SOCKS5.h in Headers */, 4B6C8ADC17BD5C2E00B194F2 /* OFThread+Private.h in Headers */, 4B6C8ADD17BD5C2E00B194F2 /* OFTimer+Private.h in Headers */, + 4B4116D41F21654200E78916 /* OFURL+Private.h in Headers */, 4B853CEB1EBFDEB000A4B2C4 /* OFXMLNode+Private.h in Headers */, 4B6C8ADE17BD5C2E00B194F2 /* OFZIPArchiveEntry+Private.h in Headers */, 4B7DD58218942FE200990FD6 /* socket_helpers.h in Headers */, 4BCE4EC41ED98D1400502FF0 /* unistd_wrapper.h in Headers */, 4BFC37BD1E50E11C00EE1269 /* common.h in Headers */, @@ -3245,10 +3261,11 @@ 4B2C214B1DA292BE00735907 /* OFMutableDictionary_hashtable.m in Sources */, 4B2C214C1DA292BE00735907 /* OFMutableSet.m in Sources */, 4B2C214D1DA292BE00735907 /* OFMutableSet_hashtable.m in Sources */, 4B2C214E1DA292BE00735907 /* OFMutableString.m in Sources */, 4B2C214F1DA292BE00735907 /* OFMutableString_UTF8.m in Sources */, + 4B4116D31F21654200E78916 /* OFMutableURL.m in Sources */, 4B2C21501DA292BE00735907 /* OFMutex.m in Sources */, 4B2C21511DA292BE00735907 /* OFNull.m in Sources */, 4B2C21521DA292BE00735907 /* OFNumber.m in Sources */, 4B2C21531DA292BE00735907 /* OFObject.m in Sources */, 4B2C21541DA292BE00735907 /* OFObject+Serialization.m in Sources */, @@ -3444,10 +3461,11 @@ 4B2B3E84140D430500EC2F7C /* OFMutableDictionary_hashtable.m in Sources */, 4B39844813D3AFB400E6F825 /* OFMutableSet.m in Sources */, 4BA85BCD140ECCE800E91D51 /* OFMutableSet_hashtable.m in Sources */, 4B3D239D1337FC0D00DD29B8 /* OFMutableString.m in Sources */, 4B552553147AA5DB0003BF47 /* OFMutableString_UTF8.m in Sources */, + 4B4116D21F21654200E78916 /* OFMutableURL.m in Sources */, 4B674404163C395900EB1E59 /* OFMutex.m in Sources */, 4B511B7D139C0A34003764A5 /* OFNull.m in Sources */, 4B3D239E1337FC0D00DD29B8 /* OFNumber.m in Sources */, 4B3D239F1337FC0D00DD29B8 /* OFObject.m in Sources */, 4BB25E89139C388A00F574EA /* OFObject+Serialization.m in Sources */, Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -38,10 +38,11 @@ OFMessagePackExtension.m \ OFMutableArray.m \ OFMutableDictionary.m \ OFMutableSet.m \ OFMutableString.m \ + OFMutableURL.m \ OFNull.m \ OFNumber.m \ OFObject.m \ OFObject+KeyValueCoding.m \ OFObject+Serialization.m \ Index: src/OFHTTPRequest.m ================================================================== --- src/OFHTTPRequest.m +++ src/OFHTTPRequest.m @@ -105,11 +105,11 @@ - initWithURL: (OFURL *)URL { self = [self init]; @try { - [self setURL: URL]; + _URL = [URL copy]; } @catch (id e) { [self release]; @throw e; } Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -618,11 +618,11 @@ return false; } - (void)createResponse { - OFURL *URL; + OFMutableURL *URL; OFHTTPRequest *request; OFHTTPServerResponse *response; size_t pos; [_timer invalidate]; @@ -638,11 +638,11 @@ [_host release]; _host = [[_server host] retain]; _port = [_server port]; } - URL = [OFURL URL]; + URL = [OFMutableURL URL]; [URL setScheme: @"http"]; [URL setHost: _host]; [URL setPort: _port]; if ((pos = [_path rangeOfString: @"?"].location) != OF_NOT_FOUND) { @@ -654,10 +654,12 @@ [URL setPath: path]; [URL setQuery: query]; } else [URL setPath: _path]; + + [URL makeImmutable]; request = [OFHTTPRequest requestWithURL: URL]; [request setMethod: _method]; [request setProtocolVersion: (of_http_request_protocol_version_t){ 1, _HTTPMinorVersion }]; ADDED src/OFMutableURL.h Index: src/OFMutableURL.h ================================================================== --- src/OFMutableURL.h +++ src/OFMutableURL.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * Jonathan Schleifer + * + * 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. + */ + +#import "OFURL.h" + +OF_ASSUME_NONNULL_BEGIN + +/*! + * @class OFMutableURL OFMutableURL.h ObjFW/OFMutableURL.h + * + * @brief A class for parsing URLs and accessing parts of it. + */ +@interface OFMutableURL: OFURL +/*! + * The scheme part of the URL. + */ +@property (readwrite, nonatomic, copy) OFString *scheme; + +/*! + * The host part of the URL. + */ +@property (readwrite, nonatomic, copy) OFString *host; + +/*! + * The port part of the URL. + */ +@property (readwrite, nonatomic) uint16_t port; + +/*! + * The user part of the URL. + */ +@property OF_NULLABLE_PROPERTY (readwrite, nonatomic, copy) OFString *user; + +/*! + * The password part of the URL. + */ +@property OF_NULLABLE_PROPERTY (readwrite, nonatomic, copy) OFString *password; + +/*! + * The path part of the URL. + */ +@property (readwrite, nonatomic, copy) OFString *path; + +/*! + * The parameters part of the URL. + */ +@property OF_NULLABLE_PROPERTY (readwrite, nonatomic, copy) + OFString *parameters; + +/*! + * The query part of the URL. + */ +@property OF_NULLABLE_PROPERTY (readwrite, nonatomic, copy) OFString *query; + +/*! + * The fragment part of the URL. + */ +@property OF_NULLABLE_PROPERTY (readwrite, nonatomic, copy) OFString *fragment; + +/*! + * @brief Creates a new mutable URL. + * + * @return A new, autoreleased OFMutableURL + */ ++ (instancetype)URL; + +/*! + * @brief Initializes an already allocated OFMutableURL. + * + * @return An initialized OFMutableURL + */ +- init; + +/*! + * @brief Converts the mutable URL to an immutable URL. + */ +- (void)makeImmutable; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFMutableURL.m Index: src/OFMutableURL.m ================================================================== --- src/OFMutableURL.m +++ src/OFMutableURL.m @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * Jonathan Schleifer + * + * 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 "OFMutableURL.h" +#import "OFURL+Private.h" + +@implementation OFMutableURL +@dynamic scheme, host, port, user, password, path, parameters, query, fragment; + ++ (instancetype)URL +{ + return [[[self alloc] init] autorelease]; +} + +- init +{ + return [super of_init]; +} + +- (void)setScheme: (OFString *)scheme +{ + OFString *old = _scheme; + _scheme = [scheme copy]; + [old release]; +} + +- (void)setHost: (OFString *)host +{ + OFString *old = _host; + _host = [host copy]; + [old release]; +} + +- (void)setPort: (uint16_t)port +{ + _port = port; +} + +- (void)setUser: (OFString *)user +{ + OFString *old = _user; + _user = [user copy]; + [old release]; +} + +- (void)setPassword: (OFString *)password +{ + OFString *old = _password; + _password = [password copy]; + [old release]; +} + +- (void)setPath: (OFString *)path +{ + OFString *old = _path; + _path = [path copy]; + [old release]; +} + +- (void)setParameters: (OFString *)parameters +{ + OFString *old = _parameters; + _parameters = [parameters copy]; + [old release]; +} + +- (void)setQuery: (OFString *)query +{ + OFString *old = _query; + _query = [query copy]; + [old release]; +} + +- (void)setFragment: (OFString *)fragment +{ + OFString *old = _fragment; + _fragment = [fragment copy]; + [old release]; +} + +- copy +{ + OFMutableURL *copy = [self mutableCopy]; + + [copy makeImmutable]; + + return copy; +} + +- (void)makeImmutable +{ + object_setClass(self, [OFURL class]); +} +@end ADDED src/OFURL+Private.h Index: src/OFURL+Private.h ================================================================== --- src/OFURL+Private.h +++ src/OFURL+Private.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * Jonathan Schleifer + * + * 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. + */ + +#import "OFURL.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFURL () +- (instancetype)of_init OF_METHOD_FAMILY(init); +@end + +OF_ASSUME_NONNULL_END Index: src/OFURL.h ================================================================== --- src/OFURL.h +++ src/OFURL.h @@ -24,68 +24,61 @@ /*! * @class OFURL OFURL.h ObjFW/OFURL.h * * @brief A class for parsing URLs and accessing parts of it. */ -@interface OFURL: OFObject +@interface OFURL: OFObject { OFString *_scheme, *_host; uint16_t _port; OFString *_user, *_password, *_path, *_parameters, *_query, *_fragment; } /*! * The scheme part of the URL. */ -@property (nonatomic, copy) OFString *scheme; +@property (readonly, nonatomic, copy) OFString *scheme; /*! * The host part of the URL. */ -@property (nonatomic, copy) OFString *host; +@property (readonly, nonatomic, copy) OFString *host; /*! * The port part of the URL. */ -@property (nonatomic) uint16_t port; +@property (readonly, nonatomic) uint16_t port; /*! * The user part of the URL. */ -@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *user; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic, copy) OFString *user; /*! * The password part of the URL. */ -@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *password; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic, copy) OFString *password; /*! * The path part of the URL. */ -@property (nonatomic, copy) OFString *path; +@property (readonly, nonatomic, copy) OFString *path; /*! * The parameters part of the URL. */ -@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *parameters; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic, copy) OFString *parameters; /*! * The query part of the URL. */ -@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *query; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic, copy) OFString *query; /*! * The fragment part of the URL. */ -@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *fragment; - -/*! - * @brief Creates a new URL. - * - * @return A new, autoreleased OFURL - */ -+ (instancetype)URL; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic, copy) OFString *fragment; /*! * @brief Creates a new URL with the specified string. * * @param string A string describing a URL @@ -109,10 +102,12 @@ * * @param path The local file path * @return A new, autoreleased OFURL */ + (instancetype)fileURLWithPath: (OFString *)path; + +- init OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFURL with the specified string. * * @param string A string describing a URL @@ -138,5 +133,7 @@ */ - (OFString *)string; @end OF_ASSUME_NONNULL_END + +#import "OFMutableURL.h" Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -18,23 +18,20 @@ #include #include #import "OFURL.h" +#import "OFURL+Private.h" #import "OFString.h" #import "OFArray.h" #import "OFXMLElement.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfMemoryException.h" @implementation OFURL -@synthesize scheme = _scheme, host = _host, port = _port, user = _user; -@synthesize password = _password, path = _path, parameters = _parameters; -@synthesize query = _query, fragment = _fragment; - + (instancetype)URL { return [[[self alloc] init] autorelease]; } @@ -50,20 +47,32 @@ relativeToURL: URL] autorelease]; } + (instancetype)fileURLWithPath: (OFString *)path { - OFURL *URL = [OFURL URL]; + OFMutableURL *URL = [OFMutableURL URL]; void *pool = objc_autoreleasePoolPush(); [URL setScheme: @"file"]; [URL setPath: [[path pathComponents] componentsJoinedByString: @"/"]]; + + [URL makeImmutable]; objc_autoreleasePoolPop(pool); return URL; } + +- init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)of_init +{ + return [super init]; +} - initWithString: (OFString *)string { char *UTF8String, *UTF8String2 = NULL; @@ -359,25 +368,75 @@ OF_HASH_FINALIZE(hash); return hash; } + +- (OFString *)scheme +{ + return _scheme; +} + +- (OFString *)host +{ + return _host; +} + +- (uint16_t)port +{ + return _port; +} + +- (OFString *)user +{ + return _user; +} + +- (OFString *)password +{ + return _password; +} + +- (OFString *)path +{ + return _path; +} + +- (OFString *)parameters +{ + return _parameters; +} + +- (OFString *)query +{ + return _query; +} + +- (OFString *)fragment +{ + return _fragment; +} - copy { - OFURL *copy = [[[self class] alloc] init]; + return [self retain]; +} + +- mutableCopy +{ + OFMutableURL *copy = [[OFMutableURL alloc] init]; @try { - copy->_scheme = [_scheme copy]; - copy->_host = [_host copy]; - copy->_port = _port; - copy->_user = [_user copy]; - copy->_password = [_password copy]; - copy->_path = [_path copy]; - copy->_parameters = [_parameters copy]; - copy->_query = [_query copy]; - copy->_fragment = [_fragment copy]; + [copy setScheme: _scheme]; + [copy setHost: _host]; + [copy setPort: _port]; + [copy setUser: _user]; + [copy setPassword: _password]; + [copy setPath: _path]; + [copy setParameters: _parameters]; + [copy setQuery: _query]; + [copy setFragment: _fragment]; } @catch (id e) { [copy release]; @throw e; } Index: tests/OFArrayTests.m ================================================================== --- tests/OFArrayTests.m +++ tests/OFArrayTests.m @@ -435,13 +435,13 @@ [OFNumber numberWithSize: 3], [OFNumber numberWithSize: 6], nil]] && [[[arrayClass arrayWithObjects: @"1", @"2", nil] valueForKey: @"@count"] isEqual: [OFNumber numberWithSize: 2]]) m[0] = [mutableArrayClass arrayWithObjects: - [OFURL URLWithString: @"http://foo.bar/"], - [OFURL URLWithString: @"http://bar.qux/"], - [OFURL URLWithString: @"http://qux.quxqux/"], nil]; + [OFMutableURL URLWithString: @"http://foo.bar/"], + [OFMutableURL URLWithString: @"http://bar.qux/"], + [OFMutableURL URLWithString: @"http://qux.quxqux/"], nil]; TEST(@"-[setValue:forKey:]", R([m[0] setValue: [OFNumber numberWithShort: 1234] forKey: @"port"]) && [m[0] isEqual: [arrayClass arrayWithObjects: [OFURL URLWithString: @"http://foo.bar:1234/"],