@@ -50,16 +50,35 @@ @interface OFURIQueryOrFragmentAllowedCharacterSet: OFURIAllowedCharacterSetBase @end @interface OFURIQueryKeyValueAllowedCharacterSet: OFURIAllowedCharacterSetBase @end + +@interface OFURIPathAllowedCharacterSetWithoutExclamationMark: + OFURIPathAllowedCharacterSet +{ + OFCharacterSet *_characterSet; + bool (*_characterIsMember)(id, SEL, OFUnichar); +} +@end + +OF_DIRECT_MEMBERS +@interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet +{ + OFCharacterSet *_characterSet; + bool (*_characterIsMember)(id, SEL, OFUnichar); +} + +- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet; +@end static OFCharacterSet *URIAllowedCharacterSet = nil; static OFCharacterSet *URISchemeAllowedCharacterSet = nil; static OFCharacterSet *URIPathAllowedCharacterSet = nil; static OFCharacterSet *URIQueryOrFragmentAllowedCharacterSet = nil; static OFCharacterSet *URIQueryKeyValueAllowedCharacterSet = nil; +static OFCharacterSet *URIPathAllowedCharacterSetWithoutExclamationMark = nil; static OFOnceControl URIAllowedCharacterSetOnce = OFOnceControlInitValue; static OFOnceControl URIQueryOrFragmentAllowedCharacterSetOnce = OFOnceControlInitValue; @@ -95,19 +114,16 @@ { URIQueryKeyValueAllowedCharacterSet = [[OFURIQueryKeyValueAllowedCharacterSet alloc] init]; } -OF_DIRECT_MEMBERS -@interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet -{ - OFCharacterSet *_characterSet; - bool (*_characterIsMember)(id, SEL, OFUnichar); -} - -- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet; -@end +static void +initURIPathAllowedCharacterSetWithoutExclamationMark(void) +{ + URIPathAllowedCharacterSetWithoutExclamationMark = + [[OFURIPathAllowedCharacterSetWithoutExclamationMark alloc] init]; +} bool OFURIIsIPv6Host(OFString *host) { const char *UTF8String = host.UTF8String; @@ -288,10 +304,43 @@ default: return false; } } @end + +@implementation OFURIPathAllowedCharacterSetWithoutExclamationMark +- (instancetype)init +{ + self = [super init]; + + @try { + _characterSet = [[OFCharacterSet URIPathAllowedCharacterSet] + retain]; + _characterIsMember = (bool (*)(id, SEL, OFUnichar)) + [_characterSet methodForSelector: + @selector(characterIsMember:)]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_characterSet release]; + + [super dealloc]; +} + +- (bool)characterIsMember: (OFUnichar)character +{ + return (character != '!' && _characterIsMember(_characterSet, + @selector(characterIsMember:), character)); +} +@end @implementation OFInvertedCharacterSetWithoutPercent - (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet { self = [super init]; @@ -396,10 +445,19 @@ OFOnce(&URIQueryOrFragmentAllowedCharacterSetOnce, initURIQueryOrFragmentAllowedCharacterSet); return URIQueryOrFragmentAllowedCharacterSet; } + ++ (OFCharacterSet *)of_URIPathAllowedCharacterSetWithoutExclamationMark +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, + initURIPathAllowedCharacterSetWithoutExclamationMark); + + return URIPathAllowedCharacterSetWithoutExclamationMark; +} @end @implementation OFURI + (instancetype)URI {