@@ -21,10 +21,12 @@ #import "OFArray.h" #import "OFDictionary.h" #import "OFIRI.h" #import "OFNumber.h" #import "OFString.h" + +#import "OFOnce.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" @@ -35,12 +37,23 @@ # include # include # undef Class #endif +@interface OFLocale () +- (instancetype)of_init OF_METHOD_FAMILY(init); +@end + +static OFOnceControl initLocaleControl = OFOnceControlInitValue; static OFLocale *currentLocale = nil; static OFDictionary *operatorPrecedences = nil; + +static void +initLocale(void) +{ + currentLocale = [[OFLocale alloc] of_init]; +} #ifndef OF_AMIGAOS static void parseLocale(char *locale, OFStringEncoding *encoding, OFString **languageCode, OFString **countryCode) @@ -310,14 +323,17 @@ @synthesize languageCode = _languageCode, countryCode = _countryCode; @synthesize encoding = _encoding, decimalSeparator = _decimalSeparator; + (void)initialize { + void *pool; OFNumber *one, *two, *three, *four; if (self != [OFLocale class]) return; + + pool = objc_autoreleasePoolPush(); /* 1 is also used to denote a unary operator. */ one = [OFNumber numberWithUnsignedInt: 1]; two = [OFNumber numberWithUnsignedInt: 2]; three = [OFNumber numberWithUnsignedInt: 3]; @@ -335,34 +351,46 @@ @"&&", three, @"||", four, @"!", one, @"is_real", one, nil]; + + objc_autoreleasePoolPop(pool); } + (OFLocale *)currentLocale { + OFOnce(&initLocaleControl, initLocale); + return currentLocale; } + (OFString *)languageCode { + OFOnce(&initLocaleControl, initLocale); + return currentLocale.languageCode; } + (OFString *)countryCode { + OFOnce(&initLocaleControl, initLocale); + return currentLocale.countryCode; } + (OFStringEncoding)encoding { + OFOnce(&initLocaleControl, initLocale); + return currentLocale.encoding; } + (OFString *)decimalSeparator { + OFOnce(&initLocaleControl, initLocale); + return currentLocale.decimalSeparator; } + (void)addLocalizationDirectoryIRI: (OFIRI *)IRI { @@ -369,20 +397,30 @@ [currentLocale addLocalizationDirectoryIRI: IRI]; } - (instancetype)init { + /* + * In the past, applications not using OFApplication were required to + * create an instance of OFLocale manually. This is no longer needed + * and +[currentLocale] creates the singleton. However, in order to not + * break old applications, this method needs to just return the + * singleton now. + */ + [self release]; + + return [OFLocale currentLocale]; +} + +- (instancetype)of_init +{ self = [super init]; @try { #ifndef OF_AMIGAOS char *locale, *messagesLocale = NULL; - if (currentLocale != nil) - @throw [OFInitializationFailedException - exceptionWithClass: self.class]; - # ifdef OF_MSDOS _encoding = OFStringEncodingCodepage437; # else _encoding = OFStringEncodingUTF8; # endif @@ -482,24 +520,14 @@ } @catch (id e) { [self release]; @throw e; } - currentLocale = self; - return self; } -- (void)dealloc -{ - [_languageCode release]; - [_countryCode release]; - [_decimalSeparator release]; - [_localizedStrings release]; - - [super dealloc]; -} +OF_SINGLETON_METHODS - (void)addLocalizationDirectoryIRI: (OFIRI *)IRI { void *pool; OFIRI *mapIRI, *localizationIRI;