Index: src/OFCharacterSet.m ================================================================== --- src/OFCharacterSet.m +++ src/OFCharacterSet.m @@ -19,23 +19,30 @@ #import "OFCharacterSet.h" #import "OFBitSetCharacterSet.h" #import "OFInvertedCharacterSet.h" #import "OFRangeCharacterSet.h" + +#import "once.h" + +@interface OFPlaceholderCharacterSet: OFCharacterSet +@end + +@interface OFWhitespaceCharacterSet: OFCharacterSet +@end static struct { Class isa; } placeholder; static OFCharacterSet *whitespaceCharacterSet = nil; -@interface OFPlaceholderCharacterSet: OFCharacterSet -@end - -@interface OFWhitespaceCharacterSet: OFCharacterSet -- (instancetype)of_init; -@end +static void +initWhitespaceCharacterSet(void) +{ + whitespaceCharacterSet = [[OFWhitespaceCharacterSet alloc] init]; +} @implementation OFPlaceholderCharacterSet - (instancetype)init { return (id)[[OFBitSetCharacterSet alloc] init]; @@ -100,11 +107,14 @@ return [[[self alloc] initWithRange: range] autorelease]; } + (OFCharacterSet *)whitespaceCharacterSet { - return [OFWhitespaceCharacterSet whitespaceCharacterSet]; + static of_once_t onceControl = OF_ONCE_INIT; + of_once(&onceControl, initWhitespaceCharacterSet); + + return whitespaceCharacterSet; } - (instancetype)init { if ([self isMemberOfClass: [OFCharacterSet class]]) { @@ -137,38 +147,15 @@ } - (OFCharacterSet *)invertedSet { return [[[OFInvertedCharacterSet alloc] - of_initWithCharacterSet: self] autorelease]; + initWithCharacterSet: self] autorelease]; } @end @implementation OFWhitespaceCharacterSet -+ (void)initialize -{ - if (self != [OFWhitespaceCharacterSet class]) - return; - - whitespaceCharacterSet = [[OFWhitespaceCharacterSet alloc] of_init]; -} - -+ (OFCharacterSet *)whitespaceCharacterSet -{ - return whitespaceCharacterSet; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)of_init -{ - return [super init]; -} - - (instancetype)autorelease { return self; } Index: src/OFInvertedCharacterSet.h ================================================================== --- src/OFInvertedCharacterSet.h +++ src/OFInvertedCharacterSet.h @@ -23,10 +23,9 @@ { OFCharacterSet *_characterSet; bool (*_characterIsMember)(id, SEL, of_unichar_t); } -- (instancetype)of_initWithCharacterSet: (OFCharacterSet *)characterSet - OF_METHOD_FAMILY(init); +- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet; @end OF_ASSUME_NONNULL_END Index: src/OFInvertedCharacterSet.m ================================================================== --- src/OFInvertedCharacterSet.m +++ src/OFInvertedCharacterSet.m @@ -26,17 +26,23 @@ - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)of_initWithCharacterSet: (OFCharacterSet *)characterSet +- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet { self = [super init]; - _characterSet = [characterSet retain]; - _characterIsMember = (bool (*)(id, SEL, of_unichar_t)) - [_characterSet methodForSelector: @selector(characterIsMember:)]; + @try { + _characterSet = [characterSet retain]; + _characterIsMember = (bool (*)(id, SEL, of_unichar_t)) + [_characterSet methodForSelector: + @selector(characterIsMember:)]; + } @catch (id e) { + [self release]; + @throw e; + } return self; } - (void)dealloc Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -32,44 +32,70 @@ #endif #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfMemoryException.h" + +#import "once.h" + +@interface OFURLAllowedCharacterSetBase: OFCharacterSet +@end + +@interface OFURLAllowedCharacterSet: OFURLAllowedCharacterSetBase +@end + +@interface OFURLSchemeAllowedCharacterSet: OFURLAllowedCharacterSetBase +@end + +@interface OFURLPathAllowedCharacterSet: OFURLAllowedCharacterSetBase +@end + +@interface OFURLQueryOrFragmentAllowedCharacterSet: OFURLAllowedCharacterSetBase +@end static OFCharacterSet *URLAllowedCharacterSet = nil; static OFCharacterSet *URLSchemeAllowedCharacterSet = nil; static OFCharacterSet *URLPathAllowedCharacterSet = nil; static OFCharacterSet *URLQueryOrFragmentAllowedCharacterSet = nil; -@interface OFURLAllowedCharacterSetBase: OFCharacterSet -- (instancetype)of_init OF_METHOD_FAMILY(init); -@end - -@interface OFURLAllowedCharacterSet: OFURLAllowedCharacterSetBase -+ (OFCharacterSet *)URLAllowedCharacterSet; -@end - -@interface OFURLSchemeAllowedCharacterSet: OFURLAllowedCharacterSetBase -+ (OFCharacterSet *)URLSchemeAllowedCharacterSet; -@end - -@interface OFURLPathAllowedCharacterSet: OFURLAllowedCharacterSetBase -+ (OFCharacterSet *)URLPathAllowedCharacterSet; -@end - -@interface OFURLQueryOrFragmentAllowedCharacterSet: OFURLAllowedCharacterSetBase -+ (OFCharacterSet *)URLQueryOrFragmentAllowedCharacterSet; -@end +static of_once_t URLAllowedCharacterSetOnce = OF_ONCE_INIT; +static of_once_t URLQueryOrFragmentAllowedCharacterSetOnce = OF_ONCE_INIT; + +static void +initURLAllowedCharacterSet(void) +{ + URLAllowedCharacterSet = [[OFURLAllowedCharacterSet alloc] init]; +} + +static void +initURLSchemeAllowedCharacterSet(void) +{ + URLSchemeAllowedCharacterSet = + [[OFURLSchemeAllowedCharacterSet alloc] init]; +} + +static void +initURLPathAllowedCharacterSet(void) +{ + URLPathAllowedCharacterSet = + [[OFURLPathAllowedCharacterSet alloc] init]; +} + +static void +initURLQueryOrFragmentAllowedCharacterSet(void) +{ + URLQueryOrFragmentAllowedCharacterSet = + [[OFURLQueryOrFragmentAllowedCharacterSet alloc] init]; +} @interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet { OFCharacterSet *_characterSet; bool (*_characterIsMember)(id, SEL, of_unichar_t); } -- (instancetype)of_initWithCharacterSet: (OFCharacterSet *)characterSet - OF_METHOD_FAMILY(init); +- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet; @end bool of_url_is_ipv6_host(OFString *host) { @@ -90,20 +116,10 @@ return hasColon; } @implementation OFURLAllowedCharacterSetBase -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)of_init -{ - return [super init]; -} - - (instancetype)autorelease { return self; } @@ -121,23 +137,10 @@ return OF_RETAIN_COUNT_MAX; } @end @implementation OFURLAllowedCharacterSet -+ (void)initialize -{ - if (self != [OFURLAllowedCharacterSet class]) - return; - - URLAllowedCharacterSet = [[OFURLAllowedCharacterSet alloc] of_init]; -} - -+ (OFCharacterSet *)URLAllowedCharacterSet -{ - return URLAllowedCharacterSet; -} - - (bool)characterIsMember: (of_unichar_t)character { if (character < CHAR_MAX && of_ascii_isalnum(character)) return true; @@ -163,24 +166,10 @@ } } @end @implementation OFURLSchemeAllowedCharacterSet -+ (void)initialize -{ - if (self != [OFURLSchemeAllowedCharacterSet class]) - return; - - URLSchemeAllowedCharacterSet = - [[OFURLSchemeAllowedCharacterSet alloc] of_init]; -} - -+ (OFCharacterSet *)URLSchemeAllowedCharacterSet -{ - return URLSchemeAllowedCharacterSet; -} - - (bool)characterIsMember: (of_unichar_t)character { if (character < CHAR_MAX && of_ascii_isalnum(character)) return true; @@ -194,24 +183,10 @@ } } @end @implementation OFURLPathAllowedCharacterSet -+ (void)initialize -{ - if (self != [OFURLPathAllowedCharacterSet class]) - return; - - URLPathAllowedCharacterSet = - [[OFURLPathAllowedCharacterSet alloc] of_init]; -} - -+ (OFCharacterSet *)URLPathAllowedCharacterSet -{ - return URLPathAllowedCharacterSet; -} - - (bool)characterIsMember: (of_unichar_t)character { if (character < CHAR_MAX && of_ascii_isalnum(character)) return true; @@ -240,24 +215,10 @@ } } @end @implementation OFURLQueryOrFragmentAllowedCharacterSet -+ (void)initialize -{ - if (self != [OFURLQueryOrFragmentAllowedCharacterSet class]) - return; - - URLQueryOrFragmentAllowedCharacterSet = - [[OFURLQueryOrFragmentAllowedCharacterSet alloc] of_init]; -} - -+ (OFCharacterSet *)URLQueryOrFragmentAllowedCharacterSet -{ - return URLQueryOrFragmentAllowedCharacterSet; -} - - (bool)characterIsMember: (of_unichar_t)character { if (character < CHAR_MAX && of_ascii_isalnum(character)) return true; @@ -287,22 +248,23 @@ } } @end @implementation OFInvertedCharacterSetWithoutPercent -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)of_initWithCharacterSet: (OFCharacterSet *)characterSet +- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet { self = [super init]; - _characterSet = [characterSet retain]; - _characterIsMember = (bool (*)(id, SEL, of_unichar_t)) - [_characterSet methodForSelector: @selector(characterIsMember:)]; + @try { + _characterSet = [characterSet retain]; + _characterIsMember = (bool (*)(id, SEL, of_unichar_t)) + [_characterSet methodForSelector: + @selector(characterIsMember:)]; + } @catch (id e) { + [self release]; + @throw e; + } return self; } - (void)dealloc @@ -323,11 +285,11 @@ of_url_verify_escaped(OFString *string, OFCharacterSet *characterSet) { void *pool = objc_autoreleasePoolPush(); characterSet = [[[OFInvertedCharacterSetWithoutPercent alloc] - of_initWithCharacterSet: characterSet] autorelease]; + initWithCharacterSet: characterSet] autorelease]; if ([string indexOfCharacterFromSet: characterSet] != OF_NOT_FOUND) @throw [OFInvalidFormatException exception]; objc_autoreleasePoolPop(pool); @@ -334,43 +296,59 @@ } @implementation OFCharacterSet (URLCharacterSets) + (OFCharacterSet *)URLSchemeAllowedCharacterSet { - return [OFURLSchemeAllowedCharacterSet URLSchemeAllowedCharacterSet]; + static of_once_t onceControl = OF_ONCE_INIT; + of_once(&onceControl, initURLSchemeAllowedCharacterSet); + + return URLSchemeAllowedCharacterSet; } + (OFCharacterSet *)URLHostAllowedCharacterSet { - return [OFURLAllowedCharacterSet URLAllowedCharacterSet]; + of_once(&URLAllowedCharacterSetOnce, initURLAllowedCharacterSet); + + return URLAllowedCharacterSet; } + (OFCharacterSet *)URLUserAllowedCharacterSet { - return [OFURLAllowedCharacterSet URLAllowedCharacterSet]; + of_once(&URLAllowedCharacterSetOnce, initURLAllowedCharacterSet); + + return URLAllowedCharacterSet; } + (OFCharacterSet *)URLPasswordAllowedCharacterSet { - return [OFURLAllowedCharacterSet URLAllowedCharacterSet]; + of_once(&URLAllowedCharacterSetOnce, initURLAllowedCharacterSet); + + return URLAllowedCharacterSet; } + (OFCharacterSet *)URLPathAllowedCharacterSet { - return [OFURLPathAllowedCharacterSet URLPathAllowedCharacterSet]; + static of_once_t onceControl = OF_ONCE_INIT; + of_once(&onceControl, initURLPathAllowedCharacterSet); + + return URLPathAllowedCharacterSet; } + (OFCharacterSet *)URLQueryAllowedCharacterSet { - return [OFURLQueryOrFragmentAllowedCharacterSet - URLQueryOrFragmentAllowedCharacterSet]; + of_once(&URLQueryOrFragmentAllowedCharacterSetOnce, + initURLQueryOrFragmentAllowedCharacterSet); + + return URLQueryOrFragmentAllowedCharacterSet; } + (OFCharacterSet *)URLFragmentAllowedCharacterSet { - return [OFURLQueryOrFragmentAllowedCharacterSet - URLQueryOrFragmentAllowedCharacterSet]; + of_once(&URLQueryOrFragmentAllowedCharacterSetOnce, + initURLQueryOrFragmentAllowedCharacterSet); + + return URLQueryOrFragmentAllowedCharacterSet; } @end @implementation OFURL + (instancetype)URL