Пример #1
0
/**
 * Returns an enumeration over the IDs of all the regions that are children of this region anywhere in the region
 * hierarchy and match the given type.  This API may return an empty enumeration if this region doesn't have any
 * sub-regions that match the given type. For example, calling this method with region "150" (Europe) and type
 * "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR" (France) - "IT" (Italy) - "DE" (Germany) etc. )
 */
StringEnumeration*
Region::getContainedRegions( URegionType type ) const {
    loadRegionData();

    UErrorCode status = U_ZERO_ERROR;
    UVector *result = new UVector(NULL, uhash_compareChars, status);
 
    StringEnumeration *cr = getContainedRegions();

    for ( int32_t i = 0 ; i < cr->count(status) ; i++ ) {
        const char *id = cr->next(NULL,status);
        const Region *r = Region::getInstance(id,status);
        if ( r->getType() == type ) {
            result->addElement((void *)&r->idStr,status);
        } else {
            StringEnumeration *children = r->getContainedRegions(type);
            for ( int32_t j = 0 ; j < children->count(status) ; j++ ) {
                const char *id2 = children->next(NULL,status);
                const Region *r2 = Region::getInstance(id2,status);
                result->addElement((void *)&r2->idStr,status);
            }
            delete children;
        }
    }
    delete cr;
    StringEnumeration* resultEnumeration = new RegionNameEnumeration(result,status);
    delete result;
    return resultEnumeration;
}
Пример #2
0
/**
 * Returns an enumeration over the IDs of all the regions that are children of this region anywhere in the region
 * hierarchy and match the given type.  This API may return an empty enumeration if this region doesn't have any
 * sub-regions that match the given type. For example, calling this method with region "150" (Europe) and type
 * "URGN_TERRITORY" returns a set containing all the territories in Europe ( "FR" (France) - "IT" (Italy) - "DE" (Germany) etc. )
 */
StringEnumeration*
Region::getContainedRegions( URegionType type, UErrorCode &status ) const {
    umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status)
    if (U_FAILURE(status)) {
        return NULL;
    }

    UVector *result = new UVector(NULL, uhash_compareChars, status);

    StringEnumeration *cr = getContainedRegions(status);

    for ( int32_t i = 0 ; i < cr->count(status) ; i++ ) {
        const char *id = cr->next(NULL,status);
        const Region *r = Region::getInstance(id,status);
        if ( r->getType() == type ) {
            result->addElement((void *)&r->idStr,status);
        } else {
            StringEnumeration *children = r->getContainedRegions(type, status);
            for ( int32_t j = 0 ; j < children->count(status) ; j++ ) {
                const char *id2 = children->next(NULL,status);
                const Region *r2 = Region::getInstance(id2,status);
                result->addElement((void *)&r2->idStr,status);
            }
            delete children;
        }
    }
    delete cr;
    StringEnumeration* resultEnumeration = new RegionNameEnumeration(result,status);
    delete result;
    return resultEnumeration;
}
Пример #3
0
status_t
BLocaleRoster::GetAvailableTimeZonesForCountry(BMessage* timeZones,
	const char* countryCode) const
{
	if (!timeZones)
		return B_BAD_VALUE;

	status_t status = B_OK;

	StringEnumeration* zoneList = TimeZone::createEnumeration(countryCode);
		// countryCode == NULL will yield all timezones not bound to a country

	UErrorCode icuStatus = U_ZERO_ERROR;
	int32 count = zoneList->count(icuStatus);
	if (U_SUCCESS(icuStatus)) {
		for (int i = 0; i < count; ++i) {
			const char* zoneID = zoneList->next(NULL, icuStatus);
			if (zoneID == NULL || !U_SUCCESS(icuStatus)) {
				status = B_ERROR;
				break;
			}
			timeZones->AddString("timeZone", zoneID);
		}
	} else
		status = B_ERROR;

	delete zoneList;

	return status;
}
Пример #4
0
/**
 * Iterate through the given iterator, checking to see that all the strings
 * in the expected array are present.
 * @param expected array of strings we expect to see, or NULL
 * @param expectedCount number of elements of expected, or 0
 */
int32_t CollationServiceTest::checkStringEnumeration(const char* msg,
                                                     StringEnumeration& iter,
                                                     const char** expected,
                                                     int32_t expectedCount) {
    UErrorCode ec = U_ZERO_ERROR;
    U_ASSERT(expectedCount >= 0 && expectedCount < 31); // [sic] 31 not 32
    int32_t i = 0, idxAfterReset = 0, n = iter.count(ec);
    assertSuccess("count", ec);
    UnicodeString buf, buffAfterReset;
    int32_t seenMask = 0;
    for (;; ++i) {
        const UnicodeString* s = iter.snext(ec);
        if (!assertSuccess("snext", ec) || s == NULL)
            break;
        if (i != 0)
            buf.append(UNICODE_STRING_SIMPLE(", "));
        buf.append(*s);
        // check expected list
        for (int32_t j=0, bit=1; j<expectedCount; ++j, bit<<=1) {
            if ((seenMask&bit)==0) {
                UnicodeString exp(expected[j], (char*)NULL);
                if (*s == exp) {
                    seenMask |= bit;
                    logln((UnicodeString)"Ok: \"" + exp + "\" seen");
                }
            }
        }
    }
    // can't get pesky operator+(const US&, foo) to cooperate; use toString
#if !UCONFIG_NO_FORMATTING
    logln(UnicodeString() + msg + " = [" + buf + "] (" + toString(i) + ")");
#else
    logln(UnicodeString() + msg + " = [" + buf + "] (??? NO_FORMATTING)");
#endif
    assertTrue("count verified", i==n);
    iter.reset(ec);
    for (;; ++idxAfterReset) {
        const UChar *s = iter.unext(NULL, ec);
        if (!assertSuccess("unext", ec) || s == NULL)
            break;
        if (idxAfterReset != 0)
            buffAfterReset.append(UNICODE_STRING_SIMPLE(", "));
        buffAfterReset.append(s);
    }
    assertTrue("idxAfterReset verified", idxAfterReset==n);
    assertTrue("buffAfterReset verified", buffAfterReset==buf);
    // did we see all expected strings?
    if (((1<<expectedCount)-1) != seenMask) {
        for (int32_t j=0, bit=1; j<expectedCount; ++j, bit<<=1) {
            if ((seenMask&bit)==0) {
                errln((UnicodeString)"FAIL: \"" + expected[j] + "\" not seen");
            }
        }
    }
    return n;
}
Пример #5
0
/**
 * Set up ICU, print # of available collators
 */
void setup(UErrorCode &status) {
    u_init(&status);
  
    fprintf(stderr, "ICU %s init: %s\n", U_ICU_VERSION, u_errorName(status));

    int32_t count;
    StringEnumeration *se = Collator::getAvailableLocales();
    count = se->count(status);
    fprintf(stderr, "# Collators now available: %d,\t%s - %d providers expected.\n", count, u_errorName(status), (int32_t)PROVIDER_COUNT);
}
Пример #6
0
status_t
BLocaleRoster::GetAvailableTimeZonesWithRegionInfo(BMessage* timeZones) const
{
	if (!timeZones)
		return B_BAD_VALUE;

	status_t status = B_OK;

	UErrorCode icuStatus = U_ZERO_ERROR;

	StringEnumeration* zoneList = TimeZone::createTimeZoneIDEnumeration(
		UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, icuStatus);

	int32 count = zoneList->count(icuStatus);
	if (U_SUCCESS(icuStatus)) {
		for (int i = 0; i < count; ++i) {
			const char* zoneID = zoneList->next(NULL, icuStatus);
			if (zoneID == NULL || !U_SUCCESS(icuStatus)) {
				status = B_ERROR;
				break;
			}
			timeZones->AddString("timeZone", zoneID);

			char region[5];
			icuStatus = U_ZERO_ERROR;
			TimeZone::getRegion(zoneID, region, 5, icuStatus);
			if (!U_SUCCESS(icuStatus)) {
				status = B_ERROR;
				break;
			}
			timeZones->AddString("region", region);
		}
	} else
		status = B_ERROR;

	delete zoneList;

	return status;
}
Пример #7
0
/**
 * @bug 4151406
 * TimeZone::getAvailableIDs(int32_t) throws exception for certain values,
 * due to a faulty constant in TimeZone::java.
 */
void TimeZoneRegressionTest:: Test4151406() {
    int32_t max = 0;
    for (int32_t h=-28; h<=30; ++h) {
        // h is in half-hours from GMT; rawoffset is in millis
        int32_t rawoffset = h * 1800000;
        int32_t hh = (h<0) ? -h : h;
        UnicodeString hname = UnicodeString((h<0) ? "GMT-" : "GMT+") +
            ((hh/2 < 10) ? "0" : "") +
            (hh/2) + ':' +
            ((hh%2==0) ? "00" : "30");
        //try {
            UErrorCode ec = U_ZERO_ERROR;
            int32_t count;
            StringEnumeration* ids = TimeZone::createEnumeration(rawoffset);
            if (ids == NULL) {
                dataerrln("Fail: TimeZone::createEnumeration(rawoffset)");
                continue;
            }
            count = ids->count(ec);
            if (count> max) 
                max = count;
            if (count > 0) {
                logln(hname + ' ' + (UnicodeString)count + (UnicodeString)" e.g. " + *ids->snext(ec));
            } else {
                logln(hname + ' ' + count);
            }
            // weiv 11/27/2002: why uprv_free? This should be a delete
            delete ids;
            //delete [] ids;
            //uprv_free(ids);
        /*} catch (Exception e) {
            errln(hname + ' ' + "Fail: " + e);
        }*/
    }
    logln("Maximum zones per offset = %d", max);
}
/**
 * Test various generic API methods of DateTimePatternGenerator for API coverage.
 */
void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
{
    UnicodeString patternData[] = {
        UnicodeString("yM"),
        UnicodeString("yMMM"),
        UnicodeString("yMd"),
        UnicodeString("yMMMd"),
        UnicodeString("Md"),
        UnicodeString("MMMd"),
        UnicodeString("yQQQ"),
        UnicodeString("hhmm"),
        UnicodeString("HHmm"),
        UnicodeString("jjmm"),
        UnicodeString("mmss"),
        UnicodeString("yyyyMMMM"),
        UnicodeString(),
     };
     
    const char* testLocale[MAX_LOCALE][4] = {
        {"en", "US", "", ""},
        {"en", "US", "", "calendar=japanese"},
        {"zh", "Hans", "CN", ""},
        {"de", "DE", "", ""},
        {"fi", "", "", ""},
        {"ja", "", "", ""},
        {"ja", "", "", "calendar=japanese"},
        {"zh", "TW", "", "calendar=roc"},
     };
     
    UnicodeString patternResults[] = {
        UnicodeString("1/1999"),                              // en_US
        UnicodeString("Jan 1999"),
        UnicodeString("1/13/1999"),
        UnicodeString("Jan 13, 1999"),
        UnicodeString("1/13"),
        UnicodeString("Jan 13"),
        UnicodeString("Q1 1999"),
        UnicodeString("11:58 PM"),
        UnicodeString("23:58"),
        UnicodeString("11:58 PM"),                            // en_US  9: jjmm
        UnicodeString("58:59"),
        UnicodeString("January 1999"),                        // en_US 11: yyyyMMMM

        // currently the following for en_US@calendar=japanese just verify the correct fallback behavior for ticket:5702;
        // however some are not the "correct" results. To fix that, root needs better DateTimePatterns/availableFormats
        // data; cldrbug #1994 is for that.
        UnicodeString("H 11-01"),                             // en_US@calendar=japanese  0: yM
        UnicodeString("H 11 Jan"),                            // en_US@calendar=japanese  1: yMMM
        UnicodeString("H 11-01-13"),                          // en_US@calendar=japanese  2: yMd
        UnicodeString("H 11 Jan 13"),                         // en_US@calendar=japanese  3: yMMMd
        UnicodeString("1-13"),                                // en_US@calendar=japanese  4: Md
        UnicodeString("Jan 13"),                              // en_US@calendar=japanese  5: MMMd
        UnicodeString("H 11 Q1"),                             // en_US@calendar=japanese  6: yQQQ
        UnicodeString("11:58 PM"),                            // en_US@calendar=japanese  7: hhmm
        UnicodeString("23:58"),                               // en_US@calendar=japanese  8: HHmm
        UnicodeString("23:58"),                               // en_US@calendar=japanese  9: jjmm
        UnicodeString("58:59"),                               // en_US@calendar=japanese 10: mmss
        UnicodeString("H 11 January"),                        // en_US@calendar=japanese 11: yyyyMMMM

        UnicodeString("1999-1", -1, US_INV),                  // zh_Hans_CN: yM
        CharsToUnicodeString("1999\\u5E741\\u6708"),          // zh_Hans_CN: yMMM  -> yyyy\u5E74MMM (fixed expected result per ticket:6626:)
        CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"),
        CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // zh_Hans_CN: yMMMd -> yyyy\u5E74MMMd\u65E5 (fixed expected result per ticket:6626:)
        UnicodeString("1-13"),
        CharsToUnicodeString("1\\u670813\\u65E5"),            // zh_Hans_CN: MMMd  -> MMMd\u65E5 (fixed expected result per ticket:6626:)
        CharsToUnicodeString("1999\\u5E741\\u5B63"),
        CharsToUnicodeString("\\u4E0B\\u534811:58"),
        UnicodeString("23:58"),
        CharsToUnicodeString("\\u4E0B\\u534811:58"),          // zh_Hans_CN  9: jjmm
        UnicodeString("58:59"),
        CharsToUnicodeString("1999\\u5E741\\u6708"),          // zh_Hans_CN 11: yyyyMMMM  -> yyyy\u5E74MMM

        UnicodeString("1999-1"),  // de_DE
        UnicodeString("Jan 1999"),
        UnicodeString("13.1.1999"),
        UnicodeString("13. Jan 1999"),
        UnicodeString("13.1."),
        UnicodeString("13. Jan"),
        UnicodeString("Q1 1999"),
        UnicodeString("11:58 nachm."),
        UnicodeString("23:58"),
        UnicodeString("23:58"),                               // de  9: jjmm
        UnicodeString("58:59"),
        UnicodeString("Januar 1999"),                         // de 11: yyyyMMMM

        UnicodeString("1.1999"),                              // fi: yM (fixed expected result per ticket:6626:)
        UnicodeString("tammikuuta 1999"),
        UnicodeString("13.1.1999"),
        UnicodeString("13. tammikuuta 1999"),
        UnicodeString("13.1."),
        UnicodeString("13. tammikuuta"),
        UnicodeString("1. nelj. 1999"),
        UnicodeString("11.58 ip."),                           // fi  7: hhmm
        UnicodeString("23.58"),
        UnicodeString("23.58"),                               // fi  9: jjmm
        UnicodeString("58.59"),
        UnicodeString("tammikuuta 1999"),                     // fi 11: yyyyMMMM

        UnicodeString("1999/1"),                              // ja 0: yM    -> y/M
        CharsToUnicodeString("1999\\u5E741\\u6708"),          // ja 1: yMMM  -> y\u5E74M\u6708
        UnicodeString("1999/1/13"),                           // ja 2: yMd   -> y/M/d
        CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // ja 3: yMMMd -> y\u5E74M\u6708d\u65E5
        UnicodeString("1/13"),                                // ja 4: Md    -> M/d
        CharsToUnicodeString("1\\u670813\\u65E5"),            // ja 5: MMMd  -> M\u6708d\u65E5
        UnicodeString("1999Q1"),                              // ja 6: yQQQ  -> yQQQ
        CharsToUnicodeString("\\u5348\\u5F8C11:58"),          // ja 7: hhmm
        UnicodeString("23:58"),                               // ja 8: HHmm  -> HH:mm
        UnicodeString("23:58"),                               // ja 9: jjmm
        UnicodeString("58:59"),                               // ja 10: mmss  -> mm:ss
        CharsToUnicodeString("1999\\u5E741\\u6708"),          // ja 11: yyyyMMMM  -> y\u5E74M\u6708

        CharsToUnicodeString("\\u5E73\\u621011/1"),                       // ja@japanese 0: yM    -> Gy/m
        CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"),          // ja@japanese 1: yMMM  -> Gy\u5E74M\u6708
        CharsToUnicodeString("\\u5E73\\u621011/1/13"),                    // ja@japanese 2: yMd   -> Gy/m/d
        CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u670813\\u65E5"), // ja@japanese 3: yMMMd -> Gy\u5E74M\u6708d\u65E5
        UnicodeString("1/13"),                                            // ja@japanese 4: Md    -> M/d
        CharsToUnicodeString("1\\u670813\\u65E5"),                        // ja@japanese 5: MMMd  -> M\u6708d\u65E5
        CharsToUnicodeString("\\u5E73\\u621011/Q1"),                      // ja@japanese 6: yQQQ  -> Gy/QQQ
        CharsToUnicodeString("\\u5348\\u5F8C11:58"),                      // ja@japanese 7: hhmm  ->
        UnicodeString("23:58"),                                           // ja@japanese 8: HHmm  -> HH:mm          (as for ja)
        UnicodeString("23:58"),                                           // ja@japanese 9: jjmm
        UnicodeString("58:59"),                                           // ja@japanese 10: mmss  -> mm:ss          (as for ja)
        CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"),          // ja@japanese 11: yyyyMMMM  -> Gyyyy\u5E74M\u6708

        CharsToUnicodeString("\\u6C11\\u570B88/1"),                       // zh_TW@roc 0: yM    -> Gy/M
        CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"),          // zh_TW@roc 1: yMMM  -> Gy\u5E74M\u6708
        CharsToUnicodeString("\\u6C11\\u570B88/1/13"),                    // zh_TW@roc 2: yMd   -> Gy/M/d
        CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u670813\\u65E5"), // zh_TW@roc 3: yMMMd -> Gy\u5E74M\u6708d\u65E5
        UnicodeString("1/13"),                                            // zh_TW@roc 4: Md    -> M/d
        CharsToUnicodeString("1\\u670813\\u65E5"),                        // zh_TW@roc 5: MMMd  ->M\u6708d\u65E5
        CharsToUnicodeString("\\u6C11\\u570B88 1\\u5B63"),                // zh_TW@roc 6: yQQQ  -> Gy QQQ
        CharsToUnicodeString("\\u4E0B\\u534811:58"),                      // zh_TW@roc 7: hhmm  ->
        UnicodeString("23:58"),                                           // zh_TW@roc 8: HHmm  ->
        CharsToUnicodeString("\\u4E0B\\u534811:58"),                      // zh_TW@roc 9: jjmm
        UnicodeString("58:59"),                                           // zh_TW@roc 10: mmss  ->
        CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"),          // zh_TW@roc 11: yyyyMMMM  -> Gy\u5E74M\u670

        UnicodeString(),
    };

    UnicodeString patternTests2[] = {
        UnicodeString("yyyyMMMdd"),
        UnicodeString("yyyyqqqq"),
        UnicodeString("yMMMdd"),
        UnicodeString("EyyyyMMMdd"),
        UnicodeString("yyyyMMdd"),
        UnicodeString("yyyyMMM"),
        UnicodeString("yyyyMM"),
        UnicodeString("yyMM"),
        UnicodeString("yMMMMMd"),
        UnicodeString("EEEEEMMMMMd"),
        UnicodeString("MMMd"),
        UnicodeString("MMMdhmm"),
        UnicodeString("EMMMdhmms"),
        UnicodeString("MMdhmm"),
        UnicodeString("EEEEMMMdhmms"),
        UnicodeString("yyyyMMMddhhmmss"),
        UnicodeString("EyyyyMMMddhhmmss"),
        UnicodeString("hmm"),
        UnicodeString("hhmm"),
        UnicodeString("hhmmVVVV"),
        UnicodeString(""),
    };
    UnicodeString patternResults2[] = {
        UnicodeString("Oct 14, 1999"),
        UnicodeString("4th quarter 1999"),
        UnicodeString("Oct 14, 1999"),
        UnicodeString("Thu, Oct 14, 1999"),
        UnicodeString("10/14/1999"),
        UnicodeString("Oct 1999"),
        UnicodeString("10/1999"),
        UnicodeString("10/99"),
        UnicodeString("O 14, 1999"),
        UnicodeString("T, O 14"),
        UnicodeString("Oct 14"),
        UnicodeString("Oct 14 6:58 AM"),
        UnicodeString("Thu, Oct 14 6:58:59 AM"),
        UnicodeString("10/14 6:58 AM"),
        UnicodeString("Thursday, Oct 14 6:58:59 AM"),
        UnicodeString("Oct 14, 1999 06:58:59 AM"),
        UnicodeString("Thu, Oct 14, 1999 06:58:59 AM"),
        UnicodeString("6:58 AM"),
        UnicodeString("06:58 AM"),
        UnicodeString("06:58 AM GMT+00:00"),
        UnicodeString(""),
    };
    
    // results for getSkeletons() and getPatternForSkeleton()
    const UnicodeString testSkeletonsResults[] = { 
        UnicodeString("HH:mm"), 
        UnicodeString("MMMMd"), 
        UnicodeString("MMMMMd"), 
    };
          
    const UnicodeString testBaseSkeletonsResults[] = {        
        UnicodeString("Hm"),  
        UnicodeString("MMMd"), 
        UnicodeString("MMMd"),
    };

    UnicodeString newDecimal(" "); // space
    UnicodeString newAppendItemName("hrs.");
    UnicodeString newAppendItemFormat("{1} {0}");
    UnicodeString newDateTimeFormat("{1} {0}");
    UErrorCode status = U_ZERO_ERROR;
    UnicodeString conflictingPattern;
    UDateTimePatternConflict conflictingStatus;

    // ======= Test CreateInstance with default locale
    logln("Testing DateTimePatternGenerator createInstance from default locale");
    
    DateTimePatternGenerator *instFromDefaultLocale=DateTimePatternGenerator::createInstance(status);
    if (U_FAILURE(status)) {
        dataerrln("ERROR: Could not create DateTimePatternGenerator (default) - exitting");
        return;
    }
    else {
        delete instFromDefaultLocale;
    }

    // ======= Test CreateInstance with given locale    
    logln("Testing DateTimePatternGenerator createInstance from French locale");
    status = U_ZERO_ERROR;
    DateTimePatternGenerator *instFromLocale=DateTimePatternGenerator::createInstance(Locale::getFrench(), status);
    if (U_FAILURE(status)) {
        dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
        return;
    }

    // ======= Test clone DateTimePatternGenerator    
    logln("Testing DateTimePatternGenerator::clone()");
    status = U_ZERO_ERROR;
    

    UnicodeString decimalSymbol = instFromLocale->getDecimal();
    UnicodeString newDecimalSymbol = UnicodeString("*");
    decimalSymbol = instFromLocale->getDecimal();
    instFromLocale->setDecimal(newDecimalSymbol);
    DateTimePatternGenerator *cloneDTPatternGen=instFromLocale->clone();
    decimalSymbol = cloneDTPatternGen->getDecimal();
    if (decimalSymbol != newDecimalSymbol) {
        errln("ERROR: inconsistency is found in cloned object.");
    }
    if ( !(*cloneDTPatternGen == *instFromLocale) ) {
        errln("ERROR: inconsistency is found in cloned object.");
    }
    
    if ( *cloneDTPatternGen != *instFromLocale ) {
        errln("ERROR: inconsistency is found in cloned object.");
    }
    
    delete instFromLocale;
    delete cloneDTPatternGen;
    
    // ======= Test simple use cases    
    logln("Testing simple use cases");
    status = U_ZERO_ERROR;
    Locale deLocale=Locale::getGermany();
    UDate sampleDate=LocaleTest::date(99, 9, 13, 23, 58, 59);
    DateTimePatternGenerator *gen = DateTimePatternGenerator::createInstance(deLocale, status);
    if (U_FAILURE(status)) {
        dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getGermany()) - exitting");
        return;
    }
    UnicodeString findPattern = gen->getBestPattern(UnicodeString("MMMddHmm"), status);
    SimpleDateFormat *format = new SimpleDateFormat(findPattern, deLocale, status);
    if (U_FAILURE(status)) {
        dataerrln("ERROR: Could not create SimpleDateFormat (Locale::getGermany())");
        delete gen;
        return;
    }
    TimeZone *zone = TimeZone::createTimeZone(UnicodeString("ECT"));
    if (zone==NULL) {
        dataerrln("ERROR: Could not create TimeZone ECT");
        delete gen;
        delete format;
        return;
    }
    format->setTimeZone(*zone);
    UnicodeString dateReturned, expectedResult;
    dateReturned.remove();
    dateReturned = format->format(sampleDate, dateReturned, status);
    expectedResult=UnicodeString("14. Okt 8:58", -1, US_INV);
    if ( dateReturned != expectedResult ) {
        errln("ERROR: Simple test in getBestPattern with Locale::getGermany()).");
    }
    // add new pattern
    status = U_ZERO_ERROR;
    conflictingStatus = gen->addPattern(UnicodeString("d'. von' MMMM", -1, US_INV), true, conflictingPattern, status); 
    if (U_FAILURE(status)) {
        errln("ERROR: Could not addPattern - d\'. von\' MMMM");
    }
    status = U_ZERO_ERROR;
    UnicodeString testPattern=gen->getBestPattern(UnicodeString("MMMMdd"), status);
    testPattern=gen->getBestPattern(UnicodeString("MMMddHmm"), status);
    format->applyPattern(gen->getBestPattern(UnicodeString("MMMMddHmm"), status));
    dateReturned.remove();
    dateReturned = format->format(sampleDate, dateReturned, status);
    expectedResult=UnicodeString("14. von Oktober 8:58", -1, US_INV);
    if ( dateReturned != expectedResult ) {
        errln("ERROR: Simple test addPattern failed!: d\'. von\' MMMM  ");
    }
    delete format;
    
    // get a pattern and modify it
    format = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, 
                                                                  deLocale);
    format->setTimeZone(*zone);
    UnicodeString pattern;
    pattern = format->toPattern(pattern);
    dateReturned.remove();
    dateReturned = format->format(sampleDate, dateReturned, status);
    expectedResult=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 08:58:59 Mitteleurop\\u00E4ische Sommerzeit");
    if ( dateReturned != expectedResult ) {
        errln("ERROR: Simple test uses full date format.");
        errln(UnicodeString(" Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult);
    }
     
    // modify it to change the zone.  
    UnicodeString newPattern = gen->replaceFieldTypes(pattern, UnicodeString("vvvv"), status);
    format->applyPattern(newPattern);
    dateReturned.remove();
    dateReturned = format->format(sampleDate, dateReturned, status);
    expectedResult=UnicodeString("Donnerstag, 14. Oktober 1999 08:58:59 Frankreich");
    if ( dateReturned != expectedResult ) {
        errln("ERROR: Simple test modify the timezone!");
        errln(UnicodeString(" Got: ")+ dateReturned + UnicodeString(" Expected: ") + expectedResult);
    }
    
    // setDeciaml(), getDeciaml()
    gen->setDecimal(newDecimal);
    if (newDecimal != gen->getDecimal()) {
        errln("ERROR: unexpected result from setDecimal() and getDecimal()!.\n");
    }
    
    // setAppenItemName() , getAppendItemName()
    gen->setAppendItemName(UDATPG_HOUR_FIELD, newAppendItemName);
    if (newAppendItemName != gen->getAppendItemName(UDATPG_HOUR_FIELD)) {
        errln("ERROR: unexpected result from setAppendItemName() and getAppendItemName()!.\n");
    }
    
    // setAppenItemFormat() , getAppendItemFormat()
    gen->setAppendItemFormat(UDATPG_HOUR_FIELD, newAppendItemFormat);
    if (newAppendItemFormat != gen->getAppendItemFormat(UDATPG_HOUR_FIELD)) {
        errln("ERROR: unexpected result from setAppendItemFormat() and getAppendItemFormat()!.\n");
    }
    
    // setDateTimeFormat() , getDateTimeFormat()
    gen->setDateTimeFormat(newDateTimeFormat);
    if (newDateTimeFormat != gen->getDateTimeFormat()) {
        errln("ERROR: unexpected result from setDateTimeFormat() and getDateTimeFormat()!.\n");
    }
    
    // ======== Test getSkeleton and getBaseSkeleton
    status = U_ZERO_ERROR;
    pattern = UnicodeString("dd-MMM");
    UnicodeString expectedSkeleton = UnicodeString("MMMdd");
    UnicodeString expectedBaseSkeleton = UnicodeString("MMMd");
    UnicodeString retSkeleton = gen->getSkeleton(pattern, status);
    if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
         errln("ERROR: Unexpected result from getSkeleton().\n");
         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
    }
    retSkeleton = gen->getBaseSkeleton(pattern, status);
    if(U_FAILURE(status) || retSkeleton !=  expectedBaseSkeleton) {
         errln("ERROR: Unexpected result from getBaseSkeleton().\n");
         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
    }

    pattern = UnicodeString("dd/MMMM/yy");
    expectedSkeleton = UnicodeString("yyMMMMdd");
    expectedBaseSkeleton = UnicodeString("yMMMd");
    retSkeleton = gen->getSkeleton(pattern, status);
    if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
         errln("ERROR: Unexpected result from getSkeleton().\n");
         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
    }
    retSkeleton = gen->getBaseSkeleton(pattern, status);
    if(U_FAILURE(status) || retSkeleton !=  expectedBaseSkeleton) {
         errln("ERROR: Unexpected result from getBaseSkeleton().\n");
         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
    }
    delete format;
    delete zone;
    delete gen;
    
    {
        // Trac# 6104
        status = U_ZERO_ERROR;
        pattern = UnicodeString("YYYYMMM");
        UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
        Locale loc("ja");
        UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
        DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
        if(U_FAILURE(status)) {
            dataerrln("ERROR: Could not create DateTimePatternGenerator");
            return;
        }
        UnicodeString bPattern = patGen->getBestPattern(pattern, status);
        UnicodeString rDate;
        SimpleDateFormat sdf(bPattern, loc, status);
        rDate.remove();
        rDate = sdf.format(testDate1, rDate);

        logln(UnicodeString(" ja locale with skeleton: YYYYMMM  Best Pattern:") + bPattern);
        logln(UnicodeString("  Formatted date:") + rDate);

        if ( expR!= rDate ) {
            errln(UnicodeString("\nERROR: Test Japanese month hack Got: ") + rDate + 
                  UnicodeString(" Expected: ") + expR );
        }
        
        delete patGen;
    }
    {   // Trac# 6104
        Locale loc("zh");
        UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
        UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
        DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
        if(U_FAILURE(status)) {
            dataerrln("ERROR: Could not create DateTimePatternGenerator");
            return;
        }
        UnicodeString bPattern = patGen->getBestPattern(pattern, status);
        UnicodeString rDate;
        SimpleDateFormat sdf(bPattern, loc, status);
        rDate.remove();
        rDate = sdf.format(testDate1, rDate);

        logln(UnicodeString(" zh locale with skeleton: YYYYMMM  Best Pattern:") + bPattern);
        logln(UnicodeString("  Formatted date:") + rDate);
        if ( expR!= rDate ) {
            errln(UnicodeString("\nERROR: Test Chinese month hack Got: ") + rDate + 
                  UnicodeString(" Expected: ") + expR );
        }
        delete patGen;   
    }

    {
         // Trac# 6172 duplicate time pattern
         status = U_ZERO_ERROR;
         pattern = UnicodeString("hmv");
         UnicodeString expR = UnicodeString("h:mm a v"); // avail formats has hm -> "h:mm a" (fixed expected result per ticket:6626:)
         Locale loc("en");
         DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
         if(U_FAILURE(status)) {
             dataerrln("ERROR: Could not create DateTimePatternGenerator");
             return;
         }
         UnicodeString bPattern = patGen->getBestPattern(pattern, status);
         logln(UnicodeString(" en locale with skeleton: hmv  Best Pattern:") + bPattern);

         if ( expR!= bPattern ) {
             errln(UnicodeString("\nERROR: Test EN time format Got: ") + bPattern + 
                   UnicodeString(" Expected: ") + expR );
         }
         
         delete patGen;
     }
     
    
    // ======= Test various skeletons.
    logln("Testing DateTimePatternGenerator with various skeleton");
   
    status = U_ZERO_ERROR;
    int32_t localeIndex=0;
    int32_t resultIndex=0;
    UnicodeString resultDate;
    UDate testDate= LocaleTest::date(99, 0, 13, 23, 58, 59);
    while (localeIndex < MAX_LOCALE )
    {       
        int32_t dataIndex=0;
        UnicodeString bestPattern;
        
        Locale loc(testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]);
        logln("\n\n Locale: %s_%s_%s@%s", testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]);
        DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
        if(U_FAILURE(status)) {
            dataerrln("ERROR: Could not create DateTimePatternGenerator with locale index:%d . - exitting\n", localeIndex);
            return;
        }
        while (patternData[dataIndex].length() > 0) {
            log(patternData[dataIndex]);
            bestPattern = patGen->getBestPattern(patternData[dataIndex++], status);
            logln(UnicodeString(" -> ") + bestPattern);
            
            SimpleDateFormat sdf(bestPattern, loc, status);
            resultDate.remove();
            resultDate = sdf.format(testDate, resultDate);
            if ( resultDate != patternResults[resultIndex] ) {
                errln(UnicodeString("\nERROR: Test various skeletons[") + (dataIndex-1) + UnicodeString("], localeIndex ") + localeIndex +
                      UnicodeString(". Got: ") + resultDate + UnicodeString(" Expected: ") + patternResults[resultIndex] );
            }
            
            resultIndex++;
        }
        delete patGen;
        localeIndex++;
    }
    
    // ======= More tests ticket#6110
    logln("Testing DateTimePatternGenerator with various skeleton");
   
    status = U_ZERO_ERROR;
    localeIndex=0;
    resultIndex=0;
    testDate= LocaleTest::date(99, 9, 13, 23, 58, 59);
    {       
        int32_t dataIndex=0;
        UnicodeString bestPattern;
        logln("\n\n Test various skeletons for English locale...");
        DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(Locale::getEnglish(), status);
        if(U_FAILURE(status)) {
            dataerrln("ERROR: Could not create DateTimePatternGenerator with locale English . - exitting\n");
            return;
        }
        TimeZone *enZone = TimeZone::createTimeZone(UnicodeString("ECT/GMT"));
        if (enZone==NULL) {
            dataerrln("ERROR: Could not create TimeZone ECT");
            delete patGen;
            return;
        }
        SimpleDateFormat *enFormat = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull, 
                         DateFormat::kFull, Locale::getEnglish());
        enFormat->setTimeZone(*enZone);
        while (patternTests2[dataIndex].length() > 0) {
            logln(patternTests2[dataIndex]);
            bestPattern = patGen->getBestPattern(patternTests2[dataIndex], status);
            logln(UnicodeString(" -> ") + bestPattern);
            enFormat->applyPattern(bestPattern);
            resultDate.remove();
            resultDate = enFormat->format(testDate, resultDate);
            if ( resultDate != patternResults2[resultIndex] ) {
                errln(UnicodeString("\nERROR: Test various skeletons[") + dataIndex
                    + UnicodeString("]. Got: ") + resultDate + UnicodeString(" Expected: ") + 
                    patternResults2[resultIndex] );
            }
            dataIndex++;
            resultIndex++;
        }
        delete patGen;
        delete enZone;
        delete enFormat;
    }



    // ======= Test random skeleton 
    DateTimePatternGenerator *randDTGen= DateTimePatternGenerator::createInstance(status);
    if (U_FAILURE(status)) {
        dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
        return;
    }
    UChar newChar;
    int32_t i;
    for (i=0; i<10; ++i) {
        UnicodeString randomSkeleton;
        int32_t len = rand() % 20;
        for (int32_t j=0; j<len; ++j ) {
            while ((newChar = (UChar)(rand()%0x7f))>=(UChar)0x20) {
                randomSkeleton += newChar;
            }
        }
        UnicodeString bestPattern = randDTGen->getBestPattern(randomSkeleton, status);
    }
    delete randDTGen;
    
    // UnicodeString randomString=Unicode
    // ======= Test getStaticClassID()

    logln("Testing getStaticClassID()");
    status = U_ZERO_ERROR;
    DateTimePatternGenerator *test= DateTimePatternGenerator::createInstance(status);
    
    if(test->getDynamicClassID() != DateTimePatternGenerator::getStaticClassID()) {
        errln("ERROR: getDynamicClassID() didn't return the expected value");
    }
    delete test;
    
    // ====== Test createEmptyInstance()
    
    logln("Testing createEmptyInstance()");
    status = U_ZERO_ERROR;
    
    test = DateTimePatternGenerator::createEmptyInstance(status);
    if(U_FAILURE(status)) {
         errln("ERROR: Fail to create an empty instance ! - exitting.\n");
         delete test;
         return;
    }
    
    conflictingStatus = test->addPattern(UnicodeString("MMMMd"), true, conflictingPattern, status); 
    status = U_ZERO_ERROR;
    testPattern=test->getBestPattern(UnicodeString("MMMMdd"), status);
    conflictingStatus = test->addPattern(UnicodeString("HH:mm"), true, conflictingPattern, status); 
    conflictingStatus = test->addPattern(UnicodeString("MMMMMd"), true, conflictingPattern, status); //duplicate pattern
    StringEnumeration *output=NULL;
    output = test->getRedundants(status);
    expectedResult=UnicodeString("MMMMd");
    if (output != NULL) {
        output->reset(status);
        const UnicodeString *dupPattern=output->snext(status);
        if ( (dupPattern==NULL) || (*dupPattern != expectedResult) ) {
            errln("ERROR: Fail in getRedundants !\n");
        }
    }
    
    // ======== Test getSkeletons and getBaseSkeletons
    StringEnumeration* ptrSkeletonEnum = test->getSkeletons(status);
    if(U_FAILURE(status)) {
        errln("ERROR: Fail to get skeletons !\n");
    }
    UnicodeString returnPattern, *ptrSkeleton;
    ptrSkeletonEnum->reset(status);
    int32_t count=ptrSkeletonEnum->count(status);
    for (i=0; i<count; ++i) {
        ptrSkeleton = (UnicodeString *)ptrSkeletonEnum->snext(status);
        returnPattern = test->getPatternForSkeleton(*ptrSkeleton);
        if ( returnPattern != testSkeletonsResults[i] ) {
            errln(UnicodeString("ERROR: Unexpected result from getSkeletons and getPatternForSkeleton\nGot: ") + returnPattern
               + UnicodeString("\nExpected: ") + testSkeletonsResults[i]
               + UnicodeString("\n"));
        }
    }
    StringEnumeration* ptrBaseSkeletonEnum = test->getBaseSkeletons(status);
    if(U_FAILURE(status)) {
        errln("ERROR: Fail to get base skeletons !\n");
    }   
    count=ptrBaseSkeletonEnum->count(status);
    for (i=0; i<count; ++i) {
        ptrSkeleton = (UnicodeString *)ptrBaseSkeletonEnum->snext(status);
        if ( *ptrSkeleton != testBaseSkeletonsResults[i] ) {
            errln("ERROR: Unexpected result from getBaseSkeletons() !\n");
        }
    }

    // ========= DateTimePatternGenerator sample code in Userguide
    // set up the generator
    Locale locale = Locale::getFrench();
    status = U_ZERO_ERROR;
    DateTimePatternGenerator *generator = DateTimePatternGenerator::createInstance( locale, status);
        
    // get a pattern for an abbreviated month and day
    pattern = generator->getBestPattern(UnicodeString("MMMd"), status); 
    SimpleDateFormat formatter(pattern, locale, status); 

    zone = TimeZone::createTimeZone(UnicodeString("GMT"));
    formatter.setTimeZone(*zone);
    // use it to format (or parse)
    UnicodeString formatted;
    formatted = formatter.format(Calendar::getNow(), formatted, status); 
    // for French, the result is "13 sept."
    formatted.remove();
    // cannot use the result from getNow() because the value change evreyday.
    testDate= LocaleTest::date(99, 0, 13, 23, 58, 59);
    formatted = formatter.format(testDate, formatted, status);
    expectedResult=UnicodeString("14 janv.");
    if ( formatted != expectedResult ) {
        errln("ERROR: Userguide sample code result!");
        errln(UnicodeString(" Got: ")+ formatted + UnicodeString(" Expected: ") + expectedResult);
    }

    delete zone;
    delete output;
    delete ptrSkeletonEnum;
    delete ptrBaseSkeletonEnum;
    delete test;
    delete generator;
}
Пример #9
0
void CollationServiceTest::TestRegister()
{
#if !UCONFIG_NO_SERVICE
    // register a singleton
    const Locale& FR = Locale::getFrance();
    const Locale& US = Locale::getUS();
    const Locale US_FOO("en", "US", "FOO");

    UErrorCode status = U_ZERO_ERROR;

    Collator* frcol = Collator::createInstance(FR, status);
    Collator* uscol = Collator::createInstance(US, status);
    if(U_FAILURE(status)) {
        errcheckln(status, "Failed to create collators with %s", u_errorName(status));
        delete frcol;
        delete uscol;
        return;
    }

    { // try override en_US collator
        URegistryKey key = Collator::registerInstance(frcol, US, status);

        Collator* ncol = Collator::createInstance(US_FOO, status);
        if (*frcol != *ncol) {
            errln("register of french collator for en_US failed on request for en_US_FOO");
        }
        // ensure original collator's params not touched
        Locale loc = frcol->getLocale(ULOC_REQUESTED_LOCALE, status);
        if (loc != FR) {
          errln(UnicodeString("fr collator's requested locale changed to ") + loc.getName());
        }
        loc = frcol->getLocale(ULOC_VALID_LOCALE, status);
        if (loc != FR) {
          errln(UnicodeString("fr collator's valid locale changed to ") + loc.getName());
        }

        loc = ncol->getLocale(ULOC_REQUESTED_LOCALE, status);
        if (loc != US_FOO) {
            errln(UnicodeString("requested locale for en_US_FOO is not en_US_FOO but ") + loc.getName());
        }
        loc = ncol->getLocale(ULOC_VALID_LOCALE, status);
        if (loc != US) {
            errln(UnicodeString("valid locale for en_US_FOO is not en_US but ") + loc.getName());
        }
        loc = ncol->getLocale(ULOC_ACTUAL_LOCALE, status);
        if (loc != US) {
            errln(UnicodeString("actual locale for en_US_FOO is not en_US but ") + loc.getName());
        }
        delete ncol; ncol = NULL;

        if (!Collator::unregister(key, status)) {
            errln("failed to unregister french collator");
        }
        // !!! frcol pointer is now invalid !!!

        ncol = Collator::createInstance(US, status);
        if (*uscol != *ncol) {
            errln("collator after unregister does not match original");
        }
        delete ncol; ncol = NULL;
    }

    // recreate frcol
    frcol = Collator::createInstance(FR, status);

    LocalUCollatorPointer frFR(ucol_open("fr_FR", &status));

    { // try create collator for new locale
        Locale fu_FU_FOO("fu", "FU", "FOO");
        Locale fu_FU("fu", "FU", "");

        Collator* fucol = Collator::createInstance(fu_FU, status);
        URegistryKey key = Collator::registerInstance(frcol, fu_FU, status);
        Collator* ncol = Collator::createInstance(fu_FU_FOO, status);
        if (*frcol != *ncol) {
            errln("register of fr collator for fu_FU failed");
        }

        UnicodeString locName = fu_FU.getName();
        StringEnumeration* localeEnum = Collator::getAvailableLocales();
        UBool found = FALSE;
        const UnicodeString* locStr, *ls2;
        for (locStr = localeEnum->snext(status);
        !found && locStr != NULL;
        locStr = localeEnum->snext(status)) {
            //
            if (locName == *locStr) {
                found = TRUE;
            }
        }

        StringEnumeration *le2 = NULL;
        localeEnum->reset(status);
        int32_t i, count;
        count = localeEnum->count(status);
        for(i = 0; i < count; ++i) {
            if(i == count / 2) {
                le2 = localeEnum->clone();
                if(le2 == NULL || count != le2->count(status)) {
                    errln("ServiceEnumeration.clone() failed");
                    break;
                }
            }
            if(i >= count / 2) {
                locStr = localeEnum->snext(status);
                ls2 = le2->snext(status);
                if(*locStr != *ls2) {
                    errln("ServiceEnumeration.clone() failed for item %d", i);
                }
            } else {
                localeEnum->snext(status);
            }
        }

        delete localeEnum;
        delete le2;

        if (!found) {
            errln("new locale fu_FU not reported as supported locale");
        }

        UnicodeString displayName;
        Collator::getDisplayName(fu_FU, displayName);
        /* The locale display pattern for the locale ja, ko, and zh are different. */
        const UChar zh_fuFU_Array[] = { 0x0066, 0x0075, 0xff08, 0x0046, 0x0055, 0xff09, 0 };
        const UnicodeString zh_fuFU(zh_fuFU_Array);
        const Locale& defaultLocale = Locale::getDefault();
        if (displayName != "fu (FU)" &&
           ((defaultLocale == Locale::getKorean() && defaultLocale == Locale::getJapanese()) && displayName == "fu(FU)") &&
           ((defaultLocale == Locale::getChinese()) && displayName != zh_fuFU)) {
            errln(UnicodeString("found ") + displayName + " for fu_FU");
        }

        Collator::getDisplayName(fu_FU, fu_FU, displayName);
        if (displayName != "fu (FU)" &&
           ((defaultLocale == Locale::getKorean() && defaultLocale == Locale::getJapanese()) && displayName == "fu(FU)") &&
           ((defaultLocale == Locale::getChinese()) && displayName != zh_fuFU)) {
            errln(UnicodeString("found ") + displayName + " for fu_FU");
        }

        // test ucol_open
        LocalUCollatorPointer fufu(ucol_open("fu_FU_FOO", &status));
        if (fufu.isNull()) {
            errln("could not open fu_FU_FOO with ucol_open");
        } else {
            if (!ucol_equals(fufu.getAlias(), frFR.getAlias())) {
                errln("collator fufu != collator frFR");
            }
        }

        if (!Collator::unregister(key, status)) {
            errln("failed to unregister french collator");
        }
        // !!! note frcoll invalid again, but we're no longer using it

        // other collators should still work ok
        Locale nloc = ncol->getLocale(ULOC_VALID_LOCALE, status);
        if (nloc != fu_FU) {
            errln(UnicodeString("asked for nloc valid locale after close and got") + nloc.getName());
        }
        delete ncol; ncol = NULL;

        if (fufu.isValid()) {
            const char* nlocstr = ucol_getLocaleByType(fufu.getAlias(), ULOC_VALID_LOCALE, &status);
            if (uprv_strcmp(nlocstr, "fu_FU") != 0) {
                errln(UnicodeString("asked for uloc valid locale after close and got ") + nlocstr);
            }
        }

        ncol = Collator::createInstance(fu_FU, status);
        if (*fucol != *ncol) {
            errln("collator after unregister does not match original fu_FU");
        }
        delete uscol; uscol = NULL;
        delete ncol; ncol = NULL;
        delete fucol; fucol = NULL;
    }
#endif
}
Пример #10
0
UnicodeString& U_EXPORT2
ZoneMeta::getSingleCountry(const UnicodeString &tzid, UnicodeString &country) {
    // Get canonical country for the zone
    const UChar *region = TimeZone::getRegion(tzid);
    if (u_strcmp(gWorld, region) == 0) {
        // special case - "001"
        country.remove();
        return country;
    }

    // Checking the cached results
    UErrorCode status = U_ZERO_ERROR;
    UBool initialized;
    UMTX_CHECK(&gZoneMetaLock, gCountryInfoVectorsInitialized, initialized);
    if (!initialized) {
        // Create empty vectors
        umtx_lock(&gZoneMetaLock);
        {
            if (!gCountryInfoVectorsInitialized) {
                // No deleters for these UVectors, it's a reference to a resource bundle string.
                gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status);
                if (gSingleZoneCountries == NULL) {
                    status = U_MEMORY_ALLOCATION_ERROR;
                }
                gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status);
                if (gMultiZonesCountries == NULL) {
                    status = U_MEMORY_ALLOCATION_ERROR;
                }

                if (U_SUCCESS(status)) {
                    gCountryInfoVectorsInitialized = TRUE;
                } else {
                    delete gSingleZoneCountries;
                    delete gMultiZonesCountries;
                }
            }
        }
        umtx_unlock(&gZoneMetaLock);

        if (U_FAILURE(status)) {
            country.remove();
            return country;
        }
    }

    // Check if it was already cached
    UBool cached = FALSE;
    UBool multiZones = FALSE;
    umtx_lock(&gZoneMetaLock);
    {
        multiZones = cached = gMultiZonesCountries->contains((void*)region);
        if (!multiZones) {
            cached = gSingleZoneCountries->contains((void*)region);
        }
    }
    umtx_unlock(&gZoneMetaLock);

    if (!cached) {
        // We need to go through all zones associated with the region.
        // This is relatively heavy operation.

        U_ASSERT(u_strlen(region) == 2);

        char buf[] = {0, 0, 0};
        u_UCharsToChars(region, buf, 2);

        StringEnumeration *ids = TimeZone::createEnumeration(buf);
        int32_t idsLen = ids->count(status);
        if (U_SUCCESS(status) && idsLen > 1) {
            // multiple zones are available for the region
            UnicodeString canonical, tmp;
            const UnicodeString *id = ids->snext(status);
            getCanonicalSystemID(*id, canonical, status);
            if (U_SUCCESS(status)) {
                // check if there are any other canonical zone in the group
                while ((id = ids->snext(status))!=NULL) {
                    getCanonicalSystemID(*id, tmp, status);
                    if (U_FAILURE(status)) {
                        break;
                    }
                    if (canonical != tmp) {
                        // another canonical zone was found
                        multiZones = TRUE;
                        break;
                    }
                }
            }
        }
        if (U_FAILURE(status)) {
            // no single country by default for any error cases
            multiZones = TRUE;
        }
        delete ids;

        // Cache the result
        umtx_lock(&gZoneMetaLock);
        {
            UErrorCode ec = U_ZERO_ERROR;
            if (multiZones) {
                if (!gMultiZonesCountries->contains((void*)region)) {
                    gMultiZonesCountries->addElement((void*)region, ec);
                }
            } else {
                if (!gSingleZoneCountries->contains((void*)region)) {
                    gSingleZoneCountries->addElement((void*)region, ec);
                }
            }
        }
        umtx_unlock(&gZoneMetaLock);
    }

    if (multiZones) {
        country.remove();
    } else {
        country.setTo(region, -1);
    }
    return country;
}
Пример #11
0
UnicodeString& U_EXPORT2
ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, UBool *isPrimary /* = NULL */) {
    if (isPrimary != NULL) {
        *isPrimary = FALSE;
    }

    const UChar *region = TimeZone::getRegion(tzid);
    if (region != NULL && u_strcmp(gWorld, region) != 0) {
        country.setTo(region, -1);
    } else {
        country.setToBogus();
        return country;
    }

    if (isPrimary != NULL) {
        char regionBuf[] = {0, 0, 0};

        // Checking the cached results
        UErrorCode status = U_ZERO_ERROR;
        umtx_initOnce(gCountryInfoVectorsInitOnce, &countryInfoVectorsInit, status);
        if (U_FAILURE(status)) {
            return country;
        }

        // Check if it was already cached
        UBool cached = FALSE;
        UBool singleZone = FALSE;
        umtx_lock(gZoneMetaLock());
        {
            singleZone = cached = gSingleZoneCountries->contains((void*)region);
            if (!cached) {
                cached = gMultiZonesCountries->contains((void*)region);
            }
        }
        umtx_unlock(gZoneMetaLock());

        if (!cached) {
            // We need to go through all zones associated with the region.
            // This is relatively heavy operation.

            U_ASSERT(u_strlen(region) == 2);

            u_UCharsToChars(region, regionBuf, 2);

            StringEnumeration *ids = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, regionBuf, NULL, status);
            int32_t idsLen = ids->count(status);
            if (U_SUCCESS(status) && idsLen == 1) {
                // only the single zone is available for the region
                singleZone = TRUE;
            }
            delete ids;

            // Cache the result
            umtx_lock(gZoneMetaLock());
            {
                UErrorCode ec = U_ZERO_ERROR;
                if (singleZone) {
                    if (!gSingleZoneCountries->contains((void*)region)) {
                        gSingleZoneCountries->addElement((void*)region, ec);
                    }
                } else {
                    if (!gMultiZonesCountries->contains((void*)region)) {
                        gMultiZonesCountries->addElement((void*)region, ec);
                    }
                }
            }
            umtx_unlock(gZoneMetaLock());
        }

        if (singleZone) {
            *isPrimary = TRUE;
        } else {
            // Note: We may cache the primary zone map in future.

            // Even a country has multiple zones, one of them might be
            // dominant and treated as a primary zone
            int32_t idLen = 0;
            if (regionBuf[0] == 0) {
                u_UCharsToChars(region, regionBuf, 2);
            }

            UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status);
            ures_getByKey(rb, gPrimaryZonesTag, rb, &status);
            const UChar *primaryZone = ures_getStringByKey(rb, regionBuf, &idLen, &status);
            if (U_SUCCESS(status)) {
                if (tzid.compare(primaryZone, idLen) == 0) {
                    *isPrimary = TRUE;
                } else {
                    // The given ID might not be a canonical ID
                    UnicodeString canonicalID;
                    TimeZone::getCanonicalID(tzid, canonicalID, status);
                    if (U_SUCCESS(status) && canonicalID.compare(primaryZone, idLen) == 0) {
                        *isPrimary = TRUE;
                    }
                }
            }
            ures_close(rb);
        }
    }

    return country;
}
UHashtable*
ZoneMeta::createCanonicalMap(void) {
    UErrorCode status = U_ZERO_ERROR;

    UHashtable *canonicalMap = NULL;
    UResourceBundle *zoneFormatting = NULL;
    UResourceBundle *tzitem = NULL;
    UResourceBundle *aliases = NULL;

    StringEnumeration* tzenum = NULL;
    int32_t numZones;

    canonicalMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
    if (U_FAILURE(status)) {
        return NULL;
    }
    // no key deleter
    uhash_setValueDeleter(canonicalMap, deleteCanonicalMapEntry);

    zoneFormatting = ures_openDirect(NULL, gSupplementalData, &status);
    zoneFormatting = ures_getByKey(zoneFormatting, gZoneFormattingTag, zoneFormatting, &status);
    if (U_FAILURE(status)) {
        goto error_cleanup;
    }

    while (ures_hasNext(zoneFormatting)) {
        tzitem = ures_getNextResource(zoneFormatting, tzitem, &status);
        if (U_FAILURE(status)) {
            status = U_ZERO_ERROR;
            continue;
        }
        if (ures_getType(tzitem) != URES_TABLE) {
            continue;
        }

        int32_t canonicalLen;
        const UChar *canonical = ures_getStringByKey(tzitem, gCanonicalTag, &canonicalLen, &status);
        if (U_FAILURE(status)) {
            status = U_ZERO_ERROR;
            continue;
        }

        int32_t territoryLen;
        const UChar *territory = ures_getStringByKey(tzitem, gTerritoryTag, &territoryLen, &status);
        if (U_FAILURE(status)) {
            territory = NULL;
            status = U_ZERO_ERROR;
        }

        // Create canonical map entry
        CanonicalMapEntry *entry = (CanonicalMapEntry*)uprv_malloc(sizeof(CanonicalMapEntry));
        if (entry == NULL) {
            status = U_MEMORY_ALLOCATION_ERROR;
            goto error_cleanup;
        }
        entry->id = canonical;
        if (territory == NULL || u_strcmp(territory, gWorld) == 0) {
            entry->country = NULL;
        } else {
            entry->country = territory;
        }

        // Put this entry in the hashtable. Since this hashtable has no key deleter,
        // key is treated as const, but must be passed as non-const.
        uhash_put(canonicalMap, (UChar*)canonical, entry, &status);
        if (U_FAILURE(status)) {
            goto error_cleanup;
        }

        // Get aliases
        aliases = ures_getByKey(tzitem, gAliasesTag, aliases, &status);
        if (U_FAILURE(status)) {
            // No aliases
            status = U_ZERO_ERROR;
            continue;
        }

        while (ures_hasNext(aliases)) {
            const UChar* alias = ures_getNextString(aliases, NULL, NULL, &status);
            if (U_FAILURE(status)) {
                status = U_ZERO_ERROR;
                continue;
            }
            // Create canonical map entry for this alias
            entry = (CanonicalMapEntry*)uprv_malloc(sizeof(CanonicalMapEntry));
            if (entry == NULL) {
                status = U_MEMORY_ALLOCATION_ERROR;
                goto error_cleanup;
            }
            entry->id = canonical;
            if (territory  == NULL || u_strcmp(territory, gWorld) == 0) {
                entry->country = NULL;
            } else {
                entry->country = territory;
            }

            // Put this entry in the hashtable. Since this hashtable has no key deleter,
            // key is treated as const, but must be passed as non-const.
            uhash_put(canonicalMap, (UChar*)alias, entry, &status);
            if (U_FAILURE(status)) {
                goto error_cleanup;
            }
        }
    }

    // Some available Olson zones are not included in CLDR data (such as Asia/Riyadh87).
    // Also, when we update Olson tzdata, new zones may be added.
    // This code scans all available zones in zoneinfo.res, and if any of them are
    // missing, add them to the map.
    tzenum = TimeZone::createEnumeration();
    numZones = tzenum->count(status);
    if (U_SUCCESS(status)) {
        int32_t i;
        for (i = 0; i < numZones; i++) {
            const UnicodeString *zone = tzenum->snext(status);
            if (U_FAILURE(status)) {
                // We should not get here.
                status = U_ZERO_ERROR;
                continue;
            }
            UChar zoneUChars[ZID_KEY_MAX];
            int32_t zoneUCharsLen = zone->extract(zoneUChars, ZID_KEY_MAX, status) + 1; // Add one for NUL termination
            if (U_FAILURE(status) || status==U_STRING_NOT_TERMINATED_WARNING) {
                status = U_ZERO_ERROR;
                continue; // zone id is too long to extract
            }
            CanonicalMapEntry *entry = (CanonicalMapEntry*)uhash_get(canonicalMap, zoneUChars);
            if (entry) {
                // Already included in CLDR data
                continue;
            }
            // Not in CLDR data, but it could be new one whose alias is available
            // in CLDR.
            int32_t nTzdataEquivalent = TimeZone::countEquivalentIDs(*zone);
            int32_t j;
            for (j = 0; j < nTzdataEquivalent; j++) {
                UnicodeString alias = TimeZone::getEquivalentID(*zone, j);
                if (alias == *zone) {
                    continue;
                }
                UChar aliasUChars[ZID_KEY_MAX];
                alias.extract(aliasUChars, ZID_KEY_MAX, status);
                if (U_FAILURE(status) || status==U_STRING_NOT_TERMINATED_WARNING) {
                    status = U_ZERO_ERROR;
                    continue; // zone id is too long to extract
                }
                entry = (CanonicalMapEntry*)uhash_get(canonicalMap, aliasUChars);
                if (entry != NULL) {
                    break;
                }
            }
            // Create a new map entry
            CanonicalMapEntry* newEntry = (CanonicalMapEntry*)uprv_malloc(sizeof(CanonicalMapEntry));
            int32_t idLen;
            if (newEntry == NULL) {
                status = U_MEMORY_ALLOCATION_ERROR;
                goto error_cleanup;
            }
            if (entry == NULL) {
                // Set dereferenced zone ID as the canonical ID
                UnicodeString derefZone;
                TimeZone::dereferOlsonLink(*zone, derefZone);
                if (derefZone.length() == 0) {
                    // It should never happen.. but just in case
                    derefZone = *zone;
                }
                idLen = derefZone.length() + 1;
                newEntry->id = allocUStringInTable(idLen);
                if (newEntry->id == NULL) {
                    status = U_MEMORY_ALLOCATION_ERROR;
                    uprv_free(newEntry);
                    goto error_cleanup;
                }
                // Copy NULL terminated string
                derefZone.extract((UChar*)(newEntry->id), idLen, status);
                if (U_FAILURE(status)) {
                    removeLastUStringFromTable();
                    uprv_free(newEntry);
                    goto error_cleanup;
                }
                // No territory information available
                newEntry->country = NULL;
            } else {
                // Duplicate the entry
                newEntry->id = entry->id;
                newEntry->country = entry->country;
            }

            // Put this entry in the hashtable
            UChar *key = allocUStringInTable(zoneUCharsLen);
            if (key == NULL) {
                status = U_MEMORY_ALLOCATION_ERROR;
                deleteCanonicalMapEntry(newEntry);
                goto error_cleanup;
            }
            u_strncpy(key, zoneUChars, zoneUCharsLen);
            uhash_put(canonicalMap, key, newEntry, &status);
            if (U_FAILURE(status)) {
                goto error_cleanup;
            }
        }
    }

normal_cleanup:
    ures_close(aliases);
    ures_close(tzitem);
    ures_close(zoneFormatting);
    delete tzenum;
    return canonicalMap;

error_cleanup:
    if (canonicalMap != NULL) {
        uhash_close(canonicalMap);
        canonicalMap = NULL;
    }
    goto normal_cleanup;
}