/* ******************************************************************************* * * Copyright (C) 2000-2004, X.Net, Inc. Lafayette, California, USA * All Rights Reserved. * * Open source license http://www.opensource.org/licenses/xnet.html * * This product includes software developed by * International Business Machines Corporation and others * for use in ICU (http://oss.software.ibm.com/icu/). * ******************************************************************************* * * xiua.cpp: * Implements APIs for the Apache use of ICU * Modification History: * * Date Name Description * 09/07/01 brown initial version * 10/10/01 brown xIUA 3.1 complete * 12/06/01 brown xIUA 3.2 complete * 10/03/02 brown xIUA 3.3 complete * 12/17/02 brown xIUA 3.4 complete * 06/14/03 brown xIUA 3.5 complete (ICU 2.6 support) * 02/05/04 brown xIUA 3.6 complete (ICU 2.8 support) * 02/22/04 brown Filter times zones and build tz offset table */ #include #include #include "unicode/calendar.h" #include "xiua.h" #include "xiux.h" struct { char *country; } _territoriesTable [] = { "USASFMGUMHPRVI", "CNHKSGTW", "HKCNSGTW", "SGCNHKTW", "TWCNHKSG", NULL }; struct { char *std; } _stdtzTable [] = { "Afr", "Ame", "Ant", "Asi", "Atl", "Aus", "Eur", "Ind", "Pac", NULL }; #if (XIUA_ICU_LEVEL > 4) /* * Structure for timezone list. */ typedef struct { void * next; void * prev; int32_t offset; char tzone_name[XIUA_MAXTIMEZONESIZE]; } XIUA_TZList; typedef XIUA_TZList * XIUA_TZList_addr; struct { XIUA_TZList * next; XIUA_TZList * last; int32_t count; } static _tzOffsetTable [] = { NULL,NULL,0, /* -12 hr */ NULL,NULL,0, /* -11 hr */ NULL,NULL,0, /* -10 hr */ NULL,NULL,0, /* -9 hr */ NULL,NULL,0, /* -8 hr */ NULL,NULL,0, /* -7 hr */ NULL,NULL,0, /* -6 hr */ NULL,NULL,0, /* -5 hr */ NULL,NULL,0, /* -4 hr */ NULL,NULL,0, /* -3 hr */ NULL,NULL,0, /* -2 hr */ NULL,NULL,0, /* -1 hr */ NULL,NULL,0, /* +0 hr */ NULL,NULL,0, /* +1 hr */ NULL,NULL,0, /* +2 hr */ NULL,NULL,0, /* +3 hr */ NULL,NULL,0, /* +4 hr */ NULL,NULL,0, /* +5 hr */ NULL,NULL,0, /* +6 hr */ NULL,NULL,0, /* +7 hr */ NULL,NULL,0, /* +8 hr */ NULL,NULL,0, /* +9 hr */ NULL,NULL,0, /* +10 hr */ NULL,NULL,0, /* +11 hr */ NULL,NULL,0, /* +12 hr */ NULL,NULL,0, /* +13 hr */ NULL,NULL,0 /* +14 hr */ }; static UBool xiua_init_tz = FALSE; #endif int32_t xiua_GetNextTZone(char *target, const int32_t numBytes, int32_t * numzones, int32_t * offset, int32_t * next, int32_t * max) { XIUA_Thread * curr_thread; #if (XIUA_ICU_LEVEL > 4) int32_t i, j, k; XIUA_TZList * txOffset_Entry; XIUA_TZList * txOffset_prev; XIUA_TZList * txOffset_next; #else int32_t i; const UChar *zone; #endif int32_t tz_offset; int32_t numDispChar; curr_thread = xiux_getCurrentThread(); if (numBytes < 4) { curr_thread->status = U_BUFFER_OVERFLOW_ERROR; return 0; } curr_thread->status = U_ZERO_ERROR; #if (XIUA_ICU_LEVEL > 4) xmtx_init(NULL); xmtx_lock(NULL); if (!xiua_init_tz) { StringEnumeration* tzsm0 = TimeZone::createEnumeration(); j = tzsm0->count(curr_thread->status ); i = 0; while (inext = NULL; txOffset_Entry->prev = NULL; memset(txOffset_Entry->tzone_name,0,XIUA_MAXTIMEZONESIZE); strncpy(txOffset_Entry->tzone_name,tzsm0->next(NULL, curr_thread->status),XIUA_MAXTIMEZONESIZE-1); if (U_FAILURE(curr_thread->status)) break; i++; k = 0; while (_stdtzTable[k].std) { if(memcmp(txOffset_Entry->tzone_name,_stdtzTable[k].std,3) == 0) break; k++; } if (_stdtzTable[k].std) { txOffset_Entry->offset = xiua_GetTZoneOffset(txOffset_Entry->tzone_name); k = ((txOffset_Entry->offset + 43200) / 3600); if (_tzOffsetTable[k].next) { if (txOffset_Entry->offset % 3600) /* not even hour add to end */ { txOffset_prev = _tzOffsetTable[k].last; txOffset_Entry->prev = txOffset_prev; txOffset_prev->next = txOffset_Entry; _tzOffsetTable[k].last = txOffset_Entry; } else { txOffset_next = _tzOffsetTable[k].next; txOffset_Entry->next = txOffset_next; txOffset_next->prev = txOffset_Entry; _tzOffsetTable[k].next = txOffset_Entry; } } else { _tzOffsetTable[k].next = txOffset_Entry; _tzOffsetTable[k].last = txOffset_Entry; } _tzOffsetTable[k].count++; } } xiua_init_tz = TRUE; } xmtx_unlock(NULL); if (U_FAILURE(curr_thread->status)) return 0; #endif if (*numzones < 0) { *offset = xiua_GetTZoneOffset(NULL); *numzones = 24; } if (*numzones > 24) *numzones = 24; if (*next < 0) { *next = 0; if (*offset < -39600) *offset = 43200; if (*offset > 43200) *offset = -39600; } if (*max < 0) { if (*offset < 0) { tz_offset = (((*offset - 3599) / 3600) * 3600000); /* round to hour & sec -> millsec */ } else { tz_offset = (((*offset + 3599) / 3600) * 3600000); /* round to hour & sec -> millsec */ } *offset = tz_offset / 1000; #if (XIUA_ICU_LEVEL > 4) k = (*offset + 43200) / 3600; *max = _tzOffsetTable[k].count; #else *max = ucal_countAvailableTZIDs(tz_offset); #endif } else { tz_offset = (*offset * 1000); /* sec -> millsec */ if (*offset == 11700) tz_offset = 11224000; /* 3:15 is really 3:07:04 */ } while (*numzones) { if (*next >= *max) { if (!(*offset % 3600) && ((*offset < 43200) || (*offset >= 50400))) /* zone GMT +12 inclues up to and including GMT +14 */ { *numzones = *numzones - 1; if (numzones <= 0) break; } #if (XIUA_ICU_LEVEL > 4) *offset += 3600; k = (*offset + 43200) / 3600; *max = _tzOffsetTable[k].count; #else *offset += 900; /* 15 min */ if (*offset > 50400) *offset = -39600; /* allow up to GMT + 14 */ tz_offset = (*offset * 1000); if (*offset == 11700) tz_offset = 11224000; /* 3:15 is really 3:07:04 */ *max = ucal_countAvailableTZIDs(tz_offset); #endif if (*max == 0) continue; *next = 0; } curr_thread->status = U_ZERO_ERROR; #if (XIUA_ICU_LEVEL > 4) k = (*offset + 43200) / 3600; txOffset_next = _tzOffsetTable[k].next; memset(target,0,numBytes); i = 0; while(i<*next) { txOffset_next = (XIUA_TZList*)txOffset_next->next; i++; } strncpy(target,txOffset_next->tzone_name,numBytes-1); numDispChar = strlen(target); *next = *next + 1; if (numDispChar <= 4) continue; return numDispChar; #else zone = ucal_getAvailableTZIDs(tz_offset, *next, &curr_thread->status); if (U_FAILURE(curr_thread->status)) return 0; numDispChar = xiux_UCharsToNstr(target, (UChar *)zone, numBytes); *next = *next + 1; if (numDispChar <= 4) continue; i = 0; while (_stdtzTable[i].std) { if(memcmp(target,_stdtzTable[i].std,3) == 0) break; i++; } if (_stdtzTable[i].std) { return numDispChar; } #endif } return 0; } int32_t xiua_GetNextLocaleTZone(char *target, int32_t numBytes, int32_t * cndx, int32_t * tndx, int32_t * next, int32_t * max) { XIUA_Thread * curr_thread; XIUA_Locale * curr_locale; char cntry[ULOC_COUNTRY_CAPACITY]; const char* country; int32_t i; int32_t numDispChar; curr_thread = xiux_getCurrentThread(); if (numBytes < 4) { curr_thread->status = U_BUFFER_OVERFLOW_ERROR; return 0; } curr_thread->status = U_ZERO_ERROR; curr_locale = curr_thread->Curr_locale; uloc_getCountry(curr_locale->locale, (char*)cntry, ULOC_COUNTRY_CAPACITY, &curr_thread->status); if (U_FAILURE(curr_thread->status)) return 0; if (*cndx < 0) { i = 0; while (_territoriesTable[i].country) { if(memcmp(cntry,_territoriesTable[i].country,2) == 0) break; i++; } *cndx = i; *tndx = 0; *next = -1; *max = -1; } if (_territoriesTable[*cndx].country) { country = (const char *)(_territoriesTable[*cndx].country+(2*(*tndx))); if (!country) country = (const char *)cntry; } else { country = (const char *)cntry; } if (*max < 0) { #if (XIUA_ICU_LEVEL > 4) StringEnumeration* tzsm1 = TimeZone::createEnumeration (country); *max = tzsm1->count(curr_thread->status ); if (U_FAILURE(curr_thread->status)) return 0; delete [] tzsm1; #else const UnicodeString** tzsm1 = TimeZone::createAvailableIDs(country, *max); if(tzsm1 == 0) { curr_thread->status = U_MEMORY_ALLOCATION_ERROR; return 0; } #if (XIUA_ICU_LEVEL < 4) delete [] tzsm1; #else xiux_free(tzsm1); #endif #endif *next = 0; } if (*next < 0) { *next = 0; } while (*cndx >= 0) { if (*next >= *max) { if (!_territoriesTable[*cndx].country) { *cndx = -1; break; } *tndx = *tndx + 1; country = (const char *)(_territoriesTable[*cndx].country+(2*(*tndx))); if (!*country) { *cndx = -1; break; } #if (XIUA_ICU_LEVEL > 4) StringEnumeration* tzsm2 = TimeZone::createEnumeration (country); *max = tzsm2->count(curr_thread->status ); if (U_FAILURE(curr_thread->status)) return 0; delete [] tzsm2; #else const UnicodeString** tzsm2 = TimeZone::createAvailableIDs(country, *max); if(tzsm2 == 0) { curr_thread->status = U_MEMORY_ALLOCATION_ERROR; return 0; } #if (XIUA_ICU_LEVEL < 4) delete [] tzsm2; #else xiux_free((void *)tzsm2); #endif #endif *next = 0; } curr_thread->status = U_ZERO_ERROR; #if (XIUA_ICU_LEVEL > 4) StringEnumeration* tzs = TimeZone::createEnumeration (country); if (U_FAILURE(curr_thread->status)) return 0; memset(target,0,numBytes); i = 0; while(i<*next) { tzs->next(&numDispChar, curr_thread->status); i++; } strncpy(target,tzs->next(&numDispChar, curr_thread->status),numBytes-1); numDispChar = strlen(target); delete [] tzs; #else const UnicodeString** tzs = TimeZone::createAvailableIDs(country, *max); if(tzs == 0) { curr_thread->status = U_MEMORY_ALLOCATION_ERROR; return 0; } memset(target,0,numBytes); numDispChar = tzs[*next]->extract(0,numBytes-1,target,numBytes-1,""); #if (XIUA_ICU_LEVEL < 4) delete [] tzs; #else xiux_free(tzs); #endif #endif if (U_FAILURE(curr_thread->status)) return 0; *next = *next + 1; if (numDispChar <= 4) continue; i = 0; while (_stdtzTable[i].std) { if(memcmp(target,_stdtzTable[i].std,3) == 0) break; i++; } if (_stdtzTable[i].std) { return numDispChar; } } return 0; }