mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 08:41:03 +00:00
Various minor thread safety fixes and fallback mechanisms for bad installations.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@22524 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
1c89b5daed
commit
82a690e0bd
2 changed files with 422 additions and 122 deletions
|
@ -4,6 +4,10 @@
|
||||||
changing the current directory.
|
changing the current directory.
|
||||||
* Source/NSBundle.m: Restructure for lazy evaluation of path to
|
* Source/NSBundle.m: Restructure for lazy evaluation of path to
|
||||||
executable ... lots of apps never need it.
|
executable ... lots of apps never need it.
|
||||||
|
* Source/NSTimeZone.m: Protect some class methods using locking, and
|
||||||
|
provide (slow) fallback mechanisms if some of the files are missing,
|
||||||
|
including fallback to posix stuff in zoneinfo directory if we really
|
||||||
|
have to.
|
||||||
|
|
||||||
2006-02-20 Richard Frith-Macdonald <rfm@gnu.org>
|
2006-02-20 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,8 @@
|
||||||
/* Many systems have this file */
|
/* Many systems have this file */
|
||||||
#define SYSTEM_TIME_FILE @"/etc/localtime"
|
#define SYSTEM_TIME_FILE @"/etc/localtime"
|
||||||
|
|
||||||
|
#define POSIX_TZONES @"posix/"
|
||||||
|
|
||||||
/* Possible location of system time zone files */
|
/* Possible location of system time zone files */
|
||||||
static NSString *tzdir = nil;
|
static NSString *tzdir = nil;
|
||||||
|
|
||||||
|
@ -187,6 +189,7 @@ typedef struct {
|
||||||
{
|
{
|
||||||
@public
|
@public
|
||||||
NSString *timeZoneName;
|
NSString *timeZoneName;
|
||||||
|
NSArray *abbreviations;
|
||||||
NSData *timeZoneData;
|
NSData *timeZoneData;
|
||||||
unsigned int n_trans;
|
unsigned int n_trans;
|
||||||
unsigned int n_types;
|
unsigned int n_types;
|
||||||
|
@ -636,7 +639,7 @@ static NSMapTable *absolutes = 0;
|
||||||
char buf[9];
|
char buf[9];
|
||||||
|
|
||||||
sprintf(buf, "GMT%c%02d%02d", s, h, m);
|
sprintf(buf, "GMT%c%02d%02d", s, h, m);
|
||||||
name = [[NSString alloc] initWithCString: buf];
|
name = [[NSString alloc] initWithUTF8String: buf];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -872,22 +875,67 @@ static NSMapTable *absolutes = 0;
|
||||||
*/
|
*/
|
||||||
+ (NSDictionary*) abbreviationDictionary
|
+ (NSDictionary*) abbreviationDictionary
|
||||||
{
|
{
|
||||||
NSString *path;
|
|
||||||
if (abbreviationDictionary != nil)
|
if (abbreviationDictionary != nil)
|
||||||
return abbreviationDictionary;
|
|
||||||
|
|
||||||
path = _time_zone_path (ABBREV_DICT, @"plist");
|
|
||||||
if (path == NULL)
|
|
||||||
{
|
{
|
||||||
[NSException
|
return abbreviationDictionary;
|
||||||
raise: NSInternalInconsistencyException
|
|
||||||
format: @"Failed to open time zone abbreviation dictionary."];
|
|
||||||
}
|
}
|
||||||
abbreviationDictionary =
|
if (zone_mutex != nil)
|
||||||
[[NSString stringWithContentsOfFile: path] propertyList];
|
{
|
||||||
abbreviationDictionary =
|
[zone_mutex lock];
|
||||||
[abbreviationDictionary makeImmutableCopyOnFail: NO];
|
}
|
||||||
return RETAIN(abbreviationDictionary);
|
if (abbreviationDictionary == nil)
|
||||||
|
{
|
||||||
|
CREATE_AUTORELEASE_POOL(pool);
|
||||||
|
NSString *path;
|
||||||
|
|
||||||
|
path = _time_zone_path (ABBREV_DICT, @"plist");
|
||||||
|
if (path != nil)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Fast mechanism ... load prebuilt data from file so we don't
|
||||||
|
* need to load in all time zones.
|
||||||
|
*/
|
||||||
|
abbreviationDictionary
|
||||||
|
= RETAIN([[NSString stringWithContentsOfFile: path] propertyList]);
|
||||||
|
}
|
||||||
|
if (abbreviationDictionary == nil)
|
||||||
|
{
|
||||||
|
NSMutableDictionary *md;
|
||||||
|
NSString *name;
|
||||||
|
NSEnumerator *names;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slow fallback ... load all time zones and generate
|
||||||
|
* abbreviation dictionary from them.
|
||||||
|
*/
|
||||||
|
md = [[NSMutableDictionary alloc] init];
|
||||||
|
names = [[NSTimeZone knownTimeZoneNames] objectEnumerator];
|
||||||
|
while ((name = [names nextObject]) != nil)
|
||||||
|
{
|
||||||
|
NSTimeZone *zone;
|
||||||
|
|
||||||
|
if ((zone = [NSTimeZone timeZoneWithName: name]))
|
||||||
|
{
|
||||||
|
NSEnumerator *details;
|
||||||
|
NSTimeZoneDetail *detail;
|
||||||
|
|
||||||
|
details = [[zone timeZoneDetailArray] objectEnumerator];
|
||||||
|
while ((detail = [details nextObject]) != nil)
|
||||||
|
{
|
||||||
|
[md setObject: name forKey: [detail abbreviation]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[md makeImmutableCopyOnFail: NO];
|
||||||
|
abbreviationDictionary = md;
|
||||||
|
}
|
||||||
|
RELEASE(pool);
|
||||||
|
}
|
||||||
|
if (zone_mutex != nil)
|
||||||
|
{
|
||||||
|
[zone_mutex unlock];
|
||||||
|
}
|
||||||
|
return abbreviationDictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -896,64 +944,143 @@ static NSMapTable *absolutes = 0;
|
||||||
*/
|
*/
|
||||||
+ (NSDictionary*) abbreviationMap
|
+ (NSDictionary*) abbreviationMap
|
||||||
{
|
{
|
||||||
FILE *file; // For the file containing the abbreviation dictionary
|
|
||||||
char abbrev[80], name[80];
|
|
||||||
NSString *path;
|
|
||||||
|
|
||||||
/* Instead of creating the abbreviation dictionary when the class is
|
/* Instead of creating the abbreviation dictionary when the class is
|
||||||
initialized, we create it when we first need it, since the
|
initialized, we create it when we first need it, since the
|
||||||
dictionary can be potentially very large, considering that it's
|
dictionary can be potentially very large, considering that it's
|
||||||
almost never used. */
|
almost never used. */
|
||||||
if (abbreviationMap != nil)
|
if (abbreviationMap != nil)
|
||||||
return abbreviationMap;
|
|
||||||
|
|
||||||
/* Read dictionary from file. */
|
|
||||||
abbreviationMap = [[NSMutableDictionary alloc] init];
|
|
||||||
path = _time_zone_path (ABBREV_MAP, nil);
|
|
||||||
#if defined(__MINGW32__)
|
|
||||||
{
|
|
||||||
unichar mode[3];
|
|
||||||
mode[0] = 'r';
|
|
||||||
mode[1] = 'b';
|
|
||||||
mode[2] = '\0';
|
|
||||||
file = _wfopen((const unichar*)[path fileSystemRepresentation], mode);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
file = fopen([path fileSystemRepresentation], "r");
|
|
||||||
#endif
|
|
||||||
if (file == NULL)
|
|
||||||
[NSException
|
|
||||||
raise: NSInternalInconsistencyException
|
|
||||||
format: @"Failed to open time zone abbreviation map."];
|
|
||||||
while (fscanf(file, "%79s %79s", abbrev, name) == 2)
|
|
||||||
{
|
{
|
||||||
id a, the_name, the_abbrev;
|
return abbreviationMap;
|
||||||
|
|
||||||
the_name = [NSString stringWithCString: name];
|
|
||||||
the_abbrev = [NSString stringWithCString: abbrev];
|
|
||||||
a = [abbreviationMap objectForKey: the_abbrev];
|
|
||||||
if (a == nil)
|
|
||||||
{
|
|
||||||
a = AUTORELEASE([NSMutableArray new]);
|
|
||||||
[abbreviationMap setObject: a forKey: the_abbrev];
|
|
||||||
}
|
|
||||||
[a addObject: the_name];
|
|
||||||
}
|
}
|
||||||
fclose(file);
|
if (zone_mutex != nil)
|
||||||
|
{
|
||||||
|
[zone_mutex lock];
|
||||||
|
}
|
||||||
|
if (abbreviationMap == nil)
|
||||||
|
{
|
||||||
|
CREATE_AUTORELEASE_POOL(pool);
|
||||||
|
NSMutableDictionary *md;
|
||||||
|
NSMutableArray *ma;
|
||||||
|
NSString *the_name;
|
||||||
|
NSString *the_abbrev;
|
||||||
|
FILE *file;
|
||||||
|
char abbrev[80];
|
||||||
|
char name[80];
|
||||||
|
NSString *path;
|
||||||
|
|
||||||
/* Special case: Add the system time zone if it doesn't exist in the map */
|
/*
|
||||||
{
|
* Read dictionary from file... fast mechanism because we don't have
|
||||||
id array;
|
* to create all timezoneas and parse all their data files.
|
||||||
id the_abbrev = [systemTimeZone abbreviation];
|
*/
|
||||||
array = [abbreviationMap objectForKey: the_abbrev];
|
md = [NSMutableDictionary dictionaryWithCapacity: 100];
|
||||||
if (array == nil)
|
path = _time_zone_path (ABBREV_MAP, nil);
|
||||||
{
|
if (path != nil)
|
||||||
array = AUTORELEASE([NSMutableArray new]);
|
{
|
||||||
[abbreviationMap setObject: array forKey: the_abbrev];
|
#if defined(__MINGW32__)
|
||||||
}
|
unichar mode[3];
|
||||||
if ([array containsObject: [systemTimeZone timeZoneName]] == NO)
|
|
||||||
[array addObject: [systemTimeZone timeZoneName]];
|
mode[0] = 'r';
|
||||||
}
|
mode[1] = 'b';
|
||||||
|
mode[2] = '\0';
|
||||||
|
|
||||||
|
file = _wfopen((const unichar*)[path fileSystemRepresentation], mode);
|
||||||
|
#else
|
||||||
|
file = fopen([path fileSystemRepresentation], "r");
|
||||||
|
#endif
|
||||||
|
if (file == NULL)
|
||||||
|
{
|
||||||
|
if (zone_mutex != nil)
|
||||||
|
{
|
||||||
|
[zone_mutex unlock];
|
||||||
|
}
|
||||||
|
[NSException
|
||||||
|
raise: NSInternalInconsistencyException
|
||||||
|
format: @"Failed to open time zone abbreviation map."];
|
||||||
|
}
|
||||||
|
while (fscanf(file, "%79s %79s", abbrev, name) == 2)
|
||||||
|
{
|
||||||
|
the_name = [[NSString alloc] initWithUTF8String: name];
|
||||||
|
the_abbrev = [[NSString alloc] initWithUTF8String: abbrev];
|
||||||
|
ma = [md objectForKey: the_abbrev];
|
||||||
|
if (ma == nil)
|
||||||
|
{
|
||||||
|
ma = [[NSMutableArray alloc] initWithCapacity: 1];
|
||||||
|
[md setObject: ma forKey: the_abbrev];
|
||||||
|
RELEASE(ma);
|
||||||
|
}
|
||||||
|
RELEASE(the_abbrev);
|
||||||
|
[ma addObject: the_name];
|
||||||
|
RELEASE(the_name);
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSArray *names;
|
||||||
|
NSString *name;
|
||||||
|
NSEnumerator *e;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slow fallback mechanism ... go through all time names
|
||||||
|
* so we load all the time zone data and generate the info
|
||||||
|
* we need from it.
|
||||||
|
*/
|
||||||
|
names = [NSTimeZone knownTimeZoneNames];
|
||||||
|
for (i = 0; i < 24; i++)
|
||||||
|
{
|
||||||
|
e = [[names objectAtIndex: i] objectEnumerator];
|
||||||
|
while ((name = [e nextObject]) != nil)
|
||||||
|
{
|
||||||
|
NSTimeZone *zone;
|
||||||
|
|
||||||
|
if ((zone = [NSTimeZone timeZoneWithName: name]))
|
||||||
|
{
|
||||||
|
NSEnumerator *details;
|
||||||
|
NSTimeZoneDetail *detail;
|
||||||
|
|
||||||
|
details = [[zone timeZoneDetailArray] objectEnumerator];
|
||||||
|
while ((detail = [details nextObject]) != nil)
|
||||||
|
{
|
||||||
|
the_abbrev = [detail abbreviation];
|
||||||
|
ma = [md objectForKey: the_abbrev];
|
||||||
|
if (ma == nil)
|
||||||
|
{
|
||||||
|
ma = [[NSMutableArray alloc] initWithCapacity: 1];
|
||||||
|
[md setObject: ma forKey: the_abbrev];
|
||||||
|
RELEASE(ma);
|
||||||
|
}
|
||||||
|
[ma addObject: name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special case: Add the system time zone if
|
||||||
|
* it doesn't exist in the map */
|
||||||
|
the_abbrev = [systemTimeZone abbreviation];
|
||||||
|
ma = [md objectForKey: the_abbrev];
|
||||||
|
if (ma == nil)
|
||||||
|
{
|
||||||
|
ma = [NSMutableArray new];
|
||||||
|
[md setObject: ma forKey: the_abbrev];
|
||||||
|
RELEASE(ma);
|
||||||
|
}
|
||||||
|
the_name = [systemTimeZone timeZoneName];
|
||||||
|
if ([ma containsObject: the_name] == NO)
|
||||||
|
{
|
||||||
|
[ma addObject: the_name];
|
||||||
|
}
|
||||||
|
|
||||||
|
[md makeImmutableCopyOnFail: NO];
|
||||||
|
abbreviationMap = RETAIN(md);
|
||||||
|
RELEASE(pool);
|
||||||
|
}
|
||||||
|
if (zone_mutex != nil)
|
||||||
|
{
|
||||||
|
[zone_mutex unlock];
|
||||||
|
}
|
||||||
|
|
||||||
return abbreviationMap;
|
return abbreviationMap;
|
||||||
}
|
}
|
||||||
|
@ -964,24 +1091,40 @@ static NSMapTable *absolutes = 0;
|
||||||
+ (NSArray*) knownTimeZoneNames
|
+ (NSArray*) knownTimeZoneNames
|
||||||
{
|
{
|
||||||
static NSArray *namesArray = nil;
|
static NSArray *namesArray = nil;
|
||||||
int i;
|
|
||||||
id temp_array;
|
|
||||||
NSArray *regionsArray, *array;
|
|
||||||
|
|
||||||
/* We create the array only when we need it to reduce overhead. */
|
/* We create the array only when we need it to reduce overhead. */
|
||||||
if (namesArray != nil)
|
if (namesArray != nil)
|
||||||
return namesArray;
|
|
||||||
|
|
||||||
temp_array = [NSMutableArray array];
|
|
||||||
regionsArray = [self timeZoneArray];
|
|
||||||
|
|
||||||
for (i = 0; i < [regionsArray count]; i++)
|
|
||||||
{
|
{
|
||||||
array = [regionsArray objectAtIndex: i];
|
return namesArray;
|
||||||
[temp_array addObjectsFromArray: array];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namesArray = [[NSArray alloc] initWithArray: temp_array];
|
if (zone_mutex != nil)
|
||||||
|
{
|
||||||
|
[zone_mutex lock];
|
||||||
|
}
|
||||||
|
if (namesArray == nil)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
NSMutableArray *ma;
|
||||||
|
NSArray *regionsArray;
|
||||||
|
|
||||||
|
ma = [NSMutableArray new];
|
||||||
|
regionsArray = [self timeZoneArray];
|
||||||
|
|
||||||
|
for (i = 0; i < [regionsArray count]; i++)
|
||||||
|
{
|
||||||
|
NSArray *names = [regionsArray objectAtIndex: i];
|
||||||
|
|
||||||
|
[ma addObjectsFromArray: names];
|
||||||
|
}
|
||||||
|
|
||||||
|
[ma makeImmutableCopyOnFail: NO];
|
||||||
|
namesArray = ma;
|
||||||
|
}
|
||||||
|
if (zone_mutex != nil)
|
||||||
|
{
|
||||||
|
[zone_mutex unlock];
|
||||||
|
}
|
||||||
return namesArray;
|
return namesArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1205,8 +1348,8 @@ static NSMapTable *absolutes = 0;
|
||||||
is a symlink to the time zone. Getting the actual data (which
|
is a symlink to the time zone. Getting the actual data (which
|
||||||
is easier) doesn't help, since we won't know the name itself. */
|
is easier) doesn't help, since we won't know the name itself. */
|
||||||
#if defined(HAVE_TZHEAD) && defined(TZDEFAULT)
|
#if defined(HAVE_TZHEAD) && defined(TZDEFAULT)
|
||||||
tzdir = RETAIN([NSString stringWithCString: TZDIR]);
|
tzdir = RETAIN([NSString stringWithUTF8String: TZDIR]);
|
||||||
localZoneString = [NSString stringWithCString: TZDEFAULT];
|
localZoneString = [NSString stringWithUTF8String: TZDEFAULT];
|
||||||
localZoneString = [localZoneString stringByResolvingSymlinksInPath];
|
localZoneString = [localZoneString stringByResolvingSymlinksInPath];
|
||||||
#else
|
#else
|
||||||
NSFileManager *dflt = [NSFileManager defaultManager];
|
NSFileManager *dflt = [NSFileManager defaultManager];
|
||||||
|
@ -1257,7 +1400,7 @@ static NSMapTable *absolutes = 0;
|
||||||
{
|
{
|
||||||
tzset();
|
tzset();
|
||||||
if (tzname[0] != NULL && *tzname[0] != '\0')
|
if (tzname[0] != NULL && *tzname[0] != '\0')
|
||||||
localZoneString = [NSString stringWithCString: tzname[0]];
|
localZoneString = [NSString stringWithUTF8String: tzname[0]];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1291,7 +1434,7 @@ static NSMapTable *absolutes = 0;
|
||||||
bufsize--;
|
bufsize--;
|
||||||
}
|
}
|
||||||
localZoneString
|
localZoneString
|
||||||
= [NSString stringWithCString: buf length: bufsize];
|
= [NSString stringWithUTF8String: buf length: bufsize];
|
||||||
}
|
}
|
||||||
RegCloseKey(regkey);
|
RegCloseKey(regkey);
|
||||||
}
|
}
|
||||||
|
@ -1332,6 +1475,18 @@ static NSMapTable *absolutes = 0;
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common locations for timezone info on unix systems.
|
||||||
|
*/
|
||||||
|
static NSString *zoneDirs[] = {
|
||||||
|
@"/usr/share/zoneinfo/",
|
||||||
|
@"/usr/lib/zoneinfo/",
|
||||||
|
@"/usr/local/share/zoneinfo/",
|
||||||
|
@"/usr/local/lib/zoneinfo/",
|
||||||
|
@"/etc/zoneinfo/",
|
||||||
|
@"/usr/local/etc/zoneinfo/"
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of all the known regions.<br />
|
* Returns an array of all the known regions.<br />
|
||||||
* There are 24 elements, of course, one for each time zone.
|
* There are 24 elements, of course, one for each time zone.
|
||||||
|
@ -1341,39 +1496,159 @@ static NSMapTable *absolutes = 0;
|
||||||
+ (NSArray*) timeZoneArray
|
+ (NSArray*) timeZoneArray
|
||||||
{
|
{
|
||||||
static NSArray *regionsArray = nil;
|
static NSArray *regionsArray = nil;
|
||||||
int index, i;
|
|
||||||
char name[80];
|
|
||||||
FILE *file;
|
|
||||||
id temp_array[24];
|
|
||||||
NSString *fileName;
|
|
||||||
|
|
||||||
/* We create the array only when we need it to reduce overhead. */
|
/* We create the array only when we need it to reduce overhead. */
|
||||||
if (regionsArray != nil)
|
if (regionsArray != nil)
|
||||||
return regionsArray;
|
{
|
||||||
|
return regionsArray;
|
||||||
|
}
|
||||||
|
if (zone_mutex != nil)
|
||||||
|
{
|
||||||
|
[zone_mutex lock];
|
||||||
|
}
|
||||||
|
if (regionsArray == nil)
|
||||||
|
{
|
||||||
|
CREATE_AUTORELEASE_POOL(pool);
|
||||||
|
int index, i;
|
||||||
|
char name[80];
|
||||||
|
FILE *fp;
|
||||||
|
NSMutableArray *temp_array[24];
|
||||||
|
NSString *path;
|
||||||
|
|
||||||
for (i = 0; i < 24; i++)
|
for (i = 0; i < 24; i++)
|
||||||
temp_array[i] = [NSMutableArray array];
|
{
|
||||||
|
temp_array[i] = [NSMutableArray array];
|
||||||
|
}
|
||||||
|
|
||||||
fileName = _time_zone_path (REGIONS_FILE, nil);
|
path = _time_zone_path (REGIONS_FILE, nil);
|
||||||
|
if (path != nil)
|
||||||
|
{
|
||||||
#if defined(__MINGW32__)
|
#if defined(__MINGW32__)
|
||||||
{
|
unichar mode[3];
|
||||||
unichar mode[3];
|
|
||||||
mode[0] = 'r';
|
mode[0] = 'r';
|
||||||
mode[1] = 'b';
|
mode[1] = 'b';
|
||||||
mode[2] = '\0';
|
mode[2] = '\0';
|
||||||
file = _wfopen((const unichar*)[fileName fileSystemRepresentation], mode);
|
|
||||||
}
|
fp = _wfopen((const unichar*)[path fileSystemRepresentation], mode);
|
||||||
#else
|
#else
|
||||||
file = fopen([fileName fileSystemRepresentation], "r");
|
fp = fopen([path fileSystemRepresentation], "r");
|
||||||
#endif
|
#endif
|
||||||
if (file == NULL)
|
if (fp == NULL)
|
||||||
[NSException
|
{
|
||||||
raise: NSInternalInconsistencyException
|
if (zone_mutex != nil)
|
||||||
format: @"Failed to open time zone regions array file."];
|
{
|
||||||
while (fscanf(file, "%d %s", &index, name) == 2)
|
[zone_mutex unlock];
|
||||||
[temp_array[index] addObject: [NSString stringWithCString: name]];
|
}
|
||||||
fclose(file);
|
[NSException
|
||||||
regionsArray = [[NSArray alloc] initWithObjects: temp_array count: 24];
|
raise: NSInternalInconsistencyException
|
||||||
|
format: @"Failed to open time zone regions array file."];
|
||||||
|
}
|
||||||
|
while (fscanf(fp, "%d %s", &index, name) == 2)
|
||||||
|
{
|
||||||
|
[temp_array[index]
|
||||||
|
addObject: [NSString stringWithUTF8String: name]];
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||||
|
NSString *zonedir = nil;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(zoneDirs)/sizeof(zoneDirs[0]); i++)
|
||||||
|
{
|
||||||
|
BOOL isDir;
|
||||||
|
|
||||||
|
path = [zoneDirs[i] stringByAppendingString: POSIX_TZONES];
|
||||||
|
if ([mgr fileExistsAtPath: path isDirectory: &isDir] && isDir)
|
||||||
|
{
|
||||||
|
zonedir = path;
|
||||||
|
break; // use first one
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zonedir == nil)
|
||||||
|
{
|
||||||
|
NSLog(@"no zone directory found!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSDirectoryEnumerator *enumerator;
|
||||||
|
NSString *name;
|
||||||
|
|
||||||
|
enumerator = [mgr enumeratorAtPath: zonedir];
|
||||||
|
while ((name = [enumerator nextObject]) != nil)
|
||||||
|
{
|
||||||
|
NSTimeZone *zone = nil;
|
||||||
|
BOOL isDir;
|
||||||
|
|
||||||
|
// FIXME: check file validity.
|
||||||
|
|
||||||
|
path = [zonedir stringByAppendingString: name];
|
||||||
|
if ([mgr fileExistsAtPath: path isDirectory: &isDir]
|
||||||
|
&& isDir == NO)
|
||||||
|
{
|
||||||
|
zone = [zoneDictionary objectForKey: name];
|
||||||
|
if (zone == nil)
|
||||||
|
{
|
||||||
|
NSData *data;
|
||||||
|
|
||||||
|
data = [NSData dataWithContentsOfFile: path];
|
||||||
|
zone = [[self alloc] initWithName: name data: data];
|
||||||
|
AUTORELEASE(zone);
|
||||||
|
}
|
||||||
|
if (zone != nil)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
NSArray *details;
|
||||||
|
NSTimeZoneDetail *detail;
|
||||||
|
NSEnumerator *e;
|
||||||
|
|
||||||
|
details = [zone timeZoneDetailArray];
|
||||||
|
e = [details objectEnumerator];
|
||||||
|
|
||||||
|
while ((detail = [e nextObject]) != nil)
|
||||||
|
{
|
||||||
|
if ([detail isDaylightSavingTime] == NO)
|
||||||
|
{
|
||||||
|
break; // Found a standard time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (detail == nil && [details count] > 0)
|
||||||
|
{
|
||||||
|
// If no standard time
|
||||||
|
detail = [details objectAtIndex: 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = [detail secondsFromGMT];
|
||||||
|
if (offset < 0)
|
||||||
|
{
|
||||||
|
offset = -offset;
|
||||||
|
offset %= (60 * 60 * 24);
|
||||||
|
offset = -offset;
|
||||||
|
offset += (60 * 60 * 24);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset %= (60 * 60 * 24);
|
||||||
|
}
|
||||||
|
offset /= (60 * 60);
|
||||||
|
|
||||||
|
[temp_array[offset] addObject: name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
regionsArray = [[NSArray alloc] initWithObjects: temp_array count: 24];
|
||||||
|
RELEASE(pool);
|
||||||
|
}
|
||||||
|
if (zone_mutex != nil)
|
||||||
|
{
|
||||||
|
[zone_mutex unlock];
|
||||||
|
}
|
||||||
return regionsArray;
|
return regionsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1403,7 +1678,7 @@ static NSMapTable *absolutes = 0;
|
||||||
NSTimeZone *zone;
|
NSTimeZone *zone;
|
||||||
|
|
||||||
zone = [self timeZoneWithName: [[self abbreviationDictionary]
|
zone = [self timeZoneWithName: [[self abbreviationDictionary]
|
||||||
objectForKey: abbreviation] data: nil];
|
objectForKey: abbreviation] data: nil];
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1935,7 +2210,7 @@ int dayOfCommonEra(NSTimeInterval when);
|
||||||
int a, b;
|
int a, b;
|
||||||
|
|
||||||
ASSIGN(timeZoneName,
|
ASSIGN(timeZoneName,
|
||||||
[NSString stringWithCString: standardName]);
|
[NSString stringWithUTF8String: standardName]);
|
||||||
|
|
||||||
/* Abbr generated here is IMHO a
|
/* Abbr generated here is IMHO a
|
||||||
* bit suspicous but I kept it */
|
* bit suspicous but I kept it */
|
||||||
|
@ -1946,7 +2221,7 @@ int dayOfCommonEra(NSTimeInterval when);
|
||||||
}
|
}
|
||||||
standardName[b] = 0;
|
standardName[b] = 0;
|
||||||
ASSIGN(timeZoneNameAbbr,
|
ASSIGN(timeZoneNameAbbr,
|
||||||
[NSString stringWithCString: standardName]);
|
[NSString stringWithUTF8String: standardName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the daylight savings name for the time zone. */
|
/* Set the daylight savings name for the time zone. */
|
||||||
|
@ -1955,7 +2230,7 @@ int dayOfCommonEra(NSTimeInterval when);
|
||||||
int a, b;
|
int a, b;
|
||||||
|
|
||||||
ASSIGN(daylightZoneName,
|
ASSIGN(daylightZoneName,
|
||||||
[NSString stringWithCString: daylightName]);
|
[NSString stringWithUTF8String: daylightName]);
|
||||||
|
|
||||||
/* Abbr generated here is IMHO
|
/* Abbr generated here is IMHO
|
||||||
* a bit suspicous but I kept it */
|
* a bit suspicous but I kept it */
|
||||||
|
@ -1966,7 +2241,7 @@ int dayOfCommonEra(NSTimeInterval when);
|
||||||
}
|
}
|
||||||
daylightName[b] = 0;
|
daylightName[b] = 0;
|
||||||
ASSIGN(daylightZoneNameAbbr,
|
ASSIGN(daylightZoneNameAbbr,
|
||||||
[NSString stringWithCString: daylightName]);
|
[NSString stringWithUTF8String: daylightName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RegCloseKey(regKey);
|
RegCloseKey(regKey);
|
||||||
|
@ -2228,14 +2503,9 @@ newDetailInZoneForType(GSTimeZone *zone, TypeInfo *type)
|
||||||
{
|
{
|
||||||
RELEASE(timeZoneName);
|
RELEASE(timeZoneName);
|
||||||
RELEASE(timeZoneData);
|
RELEASE(timeZoneData);
|
||||||
|
RELEASE(abbreviations);
|
||||||
if (types != 0)
|
if (types != 0)
|
||||||
{
|
{
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
for (i = 0; i < n_types; i++)
|
|
||||||
{
|
|
||||||
RELEASE(types[i].abbreviation);
|
|
||||||
}
|
|
||||||
NSZoneFree(NSDefaultMallocZone(), types);
|
NSZoneFree(NSDefaultMallocZone(), types);
|
||||||
}
|
}
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
|
@ -2335,7 +2605,9 @@ newDetailInZoneForType(GSTimeZone *zone, TypeInfo *type)
|
||||||
}
|
}
|
||||||
abbr = (unsigned char*)(bytes + pos);
|
abbr = (unsigned char*)(bytes + pos);
|
||||||
{
|
{
|
||||||
id abbrevs[charcnt];
|
id abbrevs[charcnt];
|
||||||
|
unsigned count = 0;
|
||||||
|
unsigned used = 0;
|
||||||
|
|
||||||
memset(abbrevs, '\0', sizeof(id)*charcnt);
|
memset(abbrevs, '\0', sizeof(id)*charcnt);
|
||||||
for (i = 0; i < n_types; i++)
|
for (i = 0; i < n_types; i++)
|
||||||
|
@ -2345,14 +2617,38 @@ newDetailInZoneForType(GSTimeZone *zone, TypeInfo *type)
|
||||||
if (abbrevs[loc] == nil)
|
if (abbrevs[loc] == nil)
|
||||||
{
|
{
|
||||||
abbrevs[loc]
|
abbrevs[loc]
|
||||||
= [[NSString alloc] initWithCString: (char*)abbr + loc];
|
= [[NSString alloc] initWithUTF8String: (char*)abbr + loc];
|
||||||
}
|
count++;
|
||||||
else
|
|
||||||
{
|
|
||||||
RETAIN(abbrevs[loc]);
|
|
||||||
}
|
}
|
||||||
types[i].abbreviation = abbrevs[loc];
|
types[i].abbreviation = abbrevs[loc];
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Now we have created all the abbreviations, we put them in an
|
||||||
|
* array for easy access later and easy deallocation if/when
|
||||||
|
* the receiver is deallocated.
|
||||||
|
*/
|
||||||
|
i = charcnt;
|
||||||
|
while (i-- > count)
|
||||||
|
{
|
||||||
|
if (abbrevs[i] != nil)
|
||||||
|
{
|
||||||
|
while (abbrevs[used] != nil)
|
||||||
|
{
|
||||||
|
used++;
|
||||||
|
}
|
||||||
|
abbrevs[used] = abbrevs[i];
|
||||||
|
abbrevs[i] = nil;
|
||||||
|
if (++used >= count)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abbreviations = [[NSArray alloc] initWithObjects: abbrevs count: count];
|
||||||
|
while (count-- > 0)
|
||||||
|
{
|
||||||
|
RELEASE(abbrevs[count]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zone_mutex != nil)
|
if (zone_mutex != nil)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue