virtual void dataerrln( const UnicodeString &message ) {
     char buffer[4000];
     message.extract(0, message.length(), buffer, sizeof(buffer));
     buffer[3999] = 0; /* NULL terminate */
     log_data_err(buffer);
 }
U_CDECL_END

U_CDECL_BEGIN
static void U_CALLCONV DataDrivenPrintfPrecision(void)
{
#if !UCONFIG_NO_FORMATTING
    UErrorCode errorCode;
    TestDataModule *dataModule;
    TestData *testData;
    const DataMap *testCase;
    DataDrivenLogger logger;
    UChar uBuffer[512];
    char cBuffer[512];
    char cFormat[sizeof(cBuffer)];
    char cExpected[sizeof(cBuffer)];
    UnicodeString tempStr;
    UChar format[512];
    UChar expectedResult[512];
    UChar argument[512];
    int32_t precision;
    int32_t i;
    int8_t i8;
    int16_t i16;
    int32_t i32;
    int64_t i64;
    double dbl;
    int32_t uBufferLenReturned;

    errorCode=U_ZERO_ERROR;
    dataModule=TestDataModule::getTestDataModule("icuio", logger, errorCode);
    if(U_SUCCESS(errorCode)) {
        testData=dataModule->createTestData("printfPrecision", errorCode);
        if(U_SUCCESS(errorCode)) {
            for(i=0; testData->nextCase(testCase, errorCode); ++i) {
                if(U_FAILURE(errorCode)) {
                    log_err("error retrieving icuio/printf test case %d - %s\n",
                            i, u_errorName(errorCode));
                    errorCode=U_ZERO_ERROR;
                    continue;
                }
                u_memset(uBuffer, 0x2A, sizeof(uBuffer)/sizeof(uBuffer[0]));
                uBuffer[sizeof(uBuffer)/sizeof(uBuffer[0])-1] = 0;
                tempStr=testCase->getString("format", errorCode);
                tempStr.extract(format, sizeof(format)/sizeof(format[0]), errorCode);
                tempStr=testCase->getString("result", errorCode);
                tempStr.extract(expectedResult, sizeof(expectedResult)/sizeof(expectedResult[0]), errorCode);
                tempStr=testCase->getString("argument", errorCode);
                tempStr.extract(argument, sizeof(argument)/sizeof(argument[0]), errorCode);
                precision=testCase->getInt28("precision", errorCode);
                u_austrncpy(cBuffer, format, sizeof(cBuffer));
                if(U_FAILURE(errorCode)) {
                    log_err("error retrieving icuio/printf test case %d - %s\n",
                            i, u_errorName(errorCode));
                    errorCode=U_ZERO_ERROR;
                    continue;
                }
                log_verbose("Test %d: format=\"%s\"\n", i, cBuffer);
                switch (testCase->getString("argumentType", errorCode)[0]) {
                case 0x64:  // 'd' double
                    dbl = atof(u_austrcpy(cBuffer, argument));
                    uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, dbl);
                    break;
                case 0x31:  // '1' int8_t
                    i8 = (int8_t)uto64(argument);
                    uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i8);
                    break;
                case 0x32:  // '2' int16_t
                    i16 = (int16_t)uto64(argument);
                    uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i16);
                    break;
                case 0x34:  // '4' int32_t
                    i32 = (int32_t)uto64(argument);
                    uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i32);
                    break;
                case 0x38:  // '8' int64_t
                    i64 = uto64(argument);
                    uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, i64);
                    break;
                case 0x73:  // 's' char *
                    u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
                    uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, cBuffer);
                    break;
                case 0x53:  // 'S' UChar *
                    uBufferLenReturned = u_sprintf_u(uBuffer, format, precision, argument);
                    break;
                default:
                    uBufferLenReturned = 0;
                    log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
                }
                if (u_strcmp(uBuffer, expectedResult) != 0) {
                    u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
                    u_austrncpy(cFormat, format, sizeof(cFormat));
                    u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
                    cBuffer[sizeof(cBuffer)-1] = 0;
                    log_err("FAILURE test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
                            i, cFormat, cBuffer, cExpected);
                }
                if (uBufferLenReturned <= 0) {
                    log_err("FAILURE test case %d - \"%s\" is an empty string.\n",
                            i, cBuffer);
                }
                else if (uBuffer[uBufferLenReturned-1] == 0
                    || uBuffer[uBufferLenReturned] != 0
                    || uBuffer[uBufferLenReturned+1] != 0x2A
                    || uBuffer[uBufferLenReturned+2] != 0x2A)
                {
                    u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
                    cBuffer[sizeof(cBuffer)-1] = 0;
                    log_err("FAILURE test case %d - \"%s\" wrong amount of characters was written. Got %d.\n",
                            i, cBuffer, uBufferLenReturned);
                }
                if(U_FAILURE(errorCode)) {
                    log_err("error running icuio/printf test case %d - %s\n",
                            i, u_errorName(errorCode));
                    errorCode=U_ZERO_ERROR;
                    continue;
                }
            }
            delete testData;
        }
        delete dataModule;
    }
    else {
        log_data_err("Failed: could not load test icuio data\n");
    }
#endif
}
U_CDECL_END

U_CDECL_BEGIN
static void U_CALLCONV DataDrivenScanf(void)
{
#if !UCONFIG_NO_FORMATTING
    UErrorCode errorCode;
    TestDataModule *dataModule;
    TestData *testData;
    const DataMap *testCase;
    DataDrivenLogger logger;
    UChar uBuffer[512];
    char cBuffer[512];
    char cExpected[sizeof(cBuffer)];
    UnicodeString tempStr;
    UChar format[512];
    UChar expectedResult[512];
    UChar argument[512];
    int32_t i;
    int8_t i8, expected8;
    int16_t i16, expected16;
    int32_t i32, expected32;
    int64_t i64, expected64;
    double dbl, expectedDbl;
    volatile float flt, expectedFlt; // Use volatile in order to get around an Intel compiler issue.
    int32_t uBufferLenReturned;

    //const char *fileLocale = "en_US_POSIX";
    //int32_t uFileBufferLenReturned;
    //UFILE *testFile;

    errorCode=U_ZERO_ERROR;
    dataModule=TestDataModule::getTestDataModule("icuio", logger, errorCode);
    if(U_SUCCESS(errorCode)) {
        testData=dataModule->createTestData("scanf", errorCode);
        if(U_SUCCESS(errorCode)) {
            for(i=0; testData->nextCase(testCase, errorCode); ++i) {
                if(U_FAILURE(errorCode)) {
                    log_err("error retrieving icuio/printf test case %d - %s\n",
                            i, u_errorName(errorCode));
                    errorCode=U_ZERO_ERROR;
                    continue;
                }
/*                testFile = u_fopen(STANDARD_TEST_FILE, "w", fileLocale, "UTF-8");
                if (!testFile) {
                    log_err("Can't open test file - %s\n",
                            STANDARD_TEST_FILE);
                }*/
                u_memset(uBuffer, 0x2A, sizeof(uBuffer)/sizeof(uBuffer[0]));
                uBuffer[sizeof(uBuffer)/sizeof(uBuffer[0])-1] = 0;
                tempStr=testCase->getString("format", errorCode);
                tempStr.extract(format, sizeof(format)/sizeof(format[0]), errorCode);
                tempStr=testCase->getString("result", errorCode);
                tempStr.extract(expectedResult, sizeof(expectedResult)/sizeof(expectedResult[0]), errorCode);
                tempStr=testCase->getString("argument", errorCode);
                tempStr.extract(argument, sizeof(argument)/sizeof(argument[0]), errorCode);
                u_austrncpy(cBuffer, format, sizeof(cBuffer));
                if(U_FAILURE(errorCode)) {
                    log_err("error retrieving icuio/printf test case %d - %s\n",
                            i, u_errorName(errorCode));
                    errorCode=U_ZERO_ERROR;
                    continue;
                }
                log_verbose("Test %d: format=\"%s\"\n", i, cBuffer);
                switch (testCase->getString("argumentType", errorCode)[0]) {
                case 0x64:  // 'd' double
                    expectedDbl = atof(u_austrcpy(cBuffer, expectedResult));
                    uBufferLenReturned = u_sscanf_u(argument, format, &dbl);
                    //uFileBufferLenReturned = u_fscanf_u(testFile, format, dbl);
                    if (dbl != expectedDbl) {
                        log_err("error in scanf test case[%d] Got: %f Exp: %f\n",
                                i, dbl, expectedDbl);
                    }
                    break;
                case 0x66:  // 'f' float
                    expectedFlt = (float)atof(u_austrcpy(cBuffer, expectedResult));
                    uBufferLenReturned = u_sscanf_u(argument, format, &flt);
                    //uFileBufferLenReturned = u_fscanf_u(testFile, format, flt);
                    if (flt != expectedFlt) {
                        log_err("error in scanf test case[%d] Got: %f Exp: %f\n",
                                i, flt, expectedFlt);
                    }
                    break;
                case 0x31:  // '1' int8_t
                    expected8 = (int8_t)uto64(expectedResult);
                    uBufferLenReturned = u_sscanf_u(argument, format, &i8);
                    //uFileBufferLenReturned = u_fscanf_u(testFile, format, i8);
                    if (i8 != expected8) {
                        log_err("error in scanf test case[%d] Got: %02X Exp: %02X\n",
                                i, i8, expected8);
                    }
                    break;
                case 0x32:  // '2' int16_t
                    expected16 = (int16_t)uto64(expectedResult);
                    uBufferLenReturned = u_sscanf_u(argument, format, &i16);
                    //uFileBufferLenReturned = u_fscanf_u(testFile, format, i16);
                    if (i16 != expected16) {
                        log_err("error in scanf test case[%d] Got: %04X Exp: %04X\n",
                                i, i16, expected16);
                    }
                    break;
                case 0x34:  // '4' int32_t
                    expected32 = (int32_t)uto64(expectedResult);
                    uBufferLenReturned = u_sscanf_u(argument, format, &i32);
                    //uFileBufferLenReturned = u_fscanf_u(testFile, format, i32);
                    if (i32 != expected32) {
                        log_err("error in scanf test case[%d] Got: %08X Exp: %08X\n",
                                i, i32, expected32);
                    }
                    break;
                case 0x38:  // '8' int64_t
                    expected64 = uto64(expectedResult);
                    uBufferLenReturned = u_sscanf_u(argument, format, &i64);
                    //uFileBufferLenReturned = u_fscanf_u(testFile, format, i64);
                    if (i64 != expected64) {
                        log_err("error in scanf 64-bit. Test case = %d\n", i);
                    }
                    break;
                case 0x73:  // 's' char *
                    u_austrcpy(cExpected, expectedResult);
                    uBufferLenReturned = u_sscanf_u(argument, format, cBuffer);
                    //uFileBufferLenReturned = u_fscanf_u(testFile, format, cBuffer);
                    if (strcmp(cBuffer, cExpected) != 0) {
                        log_err("error in scanf char * string. Got \"%s\" Expected \"%s\". Test case = %d\n", cBuffer, cExpected, i);
                    }
                    break;
                case 0x53:  // 'S' UChar *
                    uBufferLenReturned = u_sscanf_u(argument, format, uBuffer);
                    //uFileBufferLenReturned = u_fscanf_u(testFile, format, argument);
                    if (u_strcmp(uBuffer, expectedResult) != 0) {
                        u_austrcpy(cExpected, format);
                        u_austrcpy(cBuffer, uBuffer);
                        log_err("error in scanf UChar * string %s Got: \"%s\". Test case = %d\n", cExpected, cBuffer, i);
                    }
                    break;
                default:
                    uBufferLenReturned = 0;
                    //uFileBufferLenReturned = 0;
                    log_err("Unknown type %c for test %d\n", testCase->getString("argumentType", errorCode)[0], i);
                }
                if (uBufferLenReturned != 1) {
                    log_err("error scanf converted %d arguments. Test case = %d\n", uBufferLenReturned, i);
                }
/*                if (u_strcmp(uBuffer, expectedResult) != 0) {
                    u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
                    u_austrncpy(cFormat, format, sizeof(cFormat));
                    u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
                    cBuffer[sizeof(cBuffer)-1] = 0;
                    log_err("FAILURE string test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
                            i, cFormat, cBuffer, cExpected);
                }
                if (uBuffer[uBufferLenReturned-1] == 0
                    || uBuffer[uBufferLenReturned] != 0
                    || uBuffer[uBufferLenReturned+1] != 0x2A
                    || uBuffer[uBufferLenReturned+2] != 0x2A)
                {
                    u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
                    cBuffer[sizeof(cBuffer)-1] = 0;
                    log_err("FAILURE test case %d - \"%s\" wrong amount of characters was written. Got %d.\n",
                            i, cBuffer, uBufferLenReturned);
                }*/
/*                u_fclose(testFile);
                testFile = u_fopen(STANDARD_TEST_FILE, "r", fileLocale, "UTF-8");
                if (!testFile) {
                    log_err("Can't open test file - %s\n",
                            STANDARD_TEST_FILE);
                }
                uBuffer[0];
                u_fgets(uBuffer, sizeof(uBuffer)/sizeof(uBuffer[0]), testFile);
                if (u_strcmp(uBuffer, expectedResult) != 0) {
                    u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
                    u_austrncpy(cFormat, format, sizeof(cFormat));
                    u_austrncpy(cExpected, expectedResult, sizeof(cExpected));
                    cBuffer[sizeof(cBuffer)-1] = 0;
                    log_err("FAILURE file test case %d \"%s\" - Got: \"%s\" Expected: \"%s\"\n",
                            i, cFormat, cBuffer, cExpected);
                }
                if (uFileBufferLenReturned != uBufferLenReturned)
                {
                    u_austrncpy(cBuffer, uBuffer, sizeof(cBuffer));
                    cBuffer[sizeof(cBuffer)-1] = 0;
                    log_err("FAILURE uFileBufferLenReturned(%d) != uBufferLenReturned(%d)\n",
                            uFileBufferLenReturned, uBufferLenReturned);
                }
*/
                if(U_FAILURE(errorCode)) {
                    log_err("error running icuio/printf test case %d - %s\n",
                            i, u_errorName(errorCode));
                    errorCode=U_ZERO_ERROR;
                    continue;
                }
//                u_fclose(testFile);
            }
            delete testData;
        }
        delete dataModule;
    }
    else {
        log_data_err("Failed: could not load test icuio data\n");
    }
#endif
}
Example #4
0
UVector*
ZoneMeta::createMetazoneMappings(const UnicodeString &tzid) {
    UVector *mzMappings = NULL;
    UErrorCode status = U_ZERO_ERROR;

    UnicodeString canonicalID;
    UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status);
    ures_getByKey(rb, gMetazoneInfo, rb, &status);
    getCanonicalCLDRID(tzid, canonicalID, status);

    if (U_SUCCESS(status)) {
        char tzKey[ZID_KEY_MAX + 1];
        int32_t tzKeyLen = canonicalID.extract(0, canonicalID.length(), tzKey, sizeof(tzKey), US_INV);
        tzKey[tzKeyLen] = 0;

        // tzid keys are using ':' as separators
        char *p = tzKey;
        while (*p) {
            if (*p == '/') {
                *p = ':';
            }
            p++;
        }

        ures_getByKey(rb, tzKey, rb, &status);

        if (U_SUCCESS(status)) {
            UResourceBundle *mz = NULL;
            while (ures_hasNext(rb)) {
                mz = ures_getNextResource(rb, mz, &status);

                const UChar *mz_name = ures_getStringByIndex(mz, 0, NULL, &status);
                const UChar *mz_from = gDefaultFrom;
                const UChar *mz_to = gDefaultTo;

                if (ures_getSize(mz) == 3) {
                    mz_from = ures_getStringByIndex(mz, 1, NULL, &status);
                    mz_to   = ures_getStringByIndex(mz, 2, NULL, &status);
                }

                if(U_FAILURE(status)){
                    status = U_ZERO_ERROR;
                    continue;
                }
                // We do not want to use SimpleDateformat to parse boundary dates,
                // because this code could be triggered by the initialization code
                // used by SimpleDateFormat.
                UDate from = parseDate(mz_from, status);
                UDate to = parseDate(mz_to, status);
                if (U_FAILURE(status)) {
                    status = U_ZERO_ERROR;
                    continue;
                }

                OlsonToMetaMappingEntry *entry = (OlsonToMetaMappingEntry*)uprv_malloc(sizeof(OlsonToMetaMappingEntry));
                if (entry == NULL) {
                    status = U_MEMORY_ALLOCATION_ERROR;
                    break;
                }
                entry->mzid = mz_name;
                entry->from = from;
                entry->to = to;

                if (mzMappings == NULL) {
                    mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status);
                    if (U_FAILURE(status)) {
                        delete mzMappings;
                        deleteOlsonToMetaMappingEntry(entry);
                        uprv_free(entry);
                        break;
                    }
                }

                mzMappings->addElement(entry, status);
                if (U_FAILURE(status)) {
                    break;
                }
            }
            ures_close(mz);
            if (U_FAILURE(status)) {
                if (mzMappings != NULL) {
                    delete mzMappings;
                    mzMappings = NULL;
                }
            }
        }
    }
    ures_close(rb);
    return mzMappings;
}
Example #5
0
const UVector* U_EXPORT2
ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) {
    UErrorCode status = U_ZERO_ERROR;
    UChar tzidUChars[ZID_KEY_MAX + 1];
    tzid.extract(tzidUChars, ZID_KEY_MAX + 1, status);
    if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
        return NULL;
    }

    UBool initialized;
    UMTX_CHECK(&gZoneMetaLock, gOlsonToMetaInitialized, initialized);
    if (!initialized) {
        UHashtable *tmpOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
        if (U_FAILURE(status)) {
            return NULL;
        }
        uhash_setKeyDeleter(tmpOlsonToMeta, deleteUCharString);
        uhash_setValueDeleter(tmpOlsonToMeta, deleteUVector);

        umtx_lock(&gZoneMetaLock);
        {
            if (!gOlsonToMetaInitialized) {
                gOlsonToMeta = tmpOlsonToMeta;
                tmpOlsonToMeta = NULL;
                gOlsonToMetaInitialized = TRUE;
            }
        }
        umtx_unlock(&gZoneMetaLock);

        // OK to call the following multiple times with the same function
        ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
        if (tmpOlsonToMeta != NULL) {
            uhash_close(tmpOlsonToMeta);
        }
    }

    // get the mapping from cache
    const UVector *result = NULL;

    umtx_lock(&gZoneMetaLock);
    {
        result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars);
    }
    umtx_unlock(&gZoneMetaLock);

    if (result != NULL) {
        return result;
    }

    // miss the cache - create new one
    UVector *tmpResult = createMetazoneMappings(tzid);
    if (tmpResult == NULL) {
        // not available
        return NULL;
    }

    // put the new one into the cache
    umtx_lock(&gZoneMetaLock);
    {
        // make sure it's already created
        result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars);
        if (result == NULL) {
            // add the one just created
            int32_t tzidLen = tzid.length() + 1;
            UChar *key = (UChar*)uprv_malloc(tzidLen * sizeof(UChar));
            if (key == NULL) {
                // memory allocation error..  just return NULL
                result = NULL;
                delete tmpResult;
            } else {
                tzid.extract(key, tzidLen, status);
                uhash_put(gOlsonToMeta, key, tmpResult, &status);
                if (U_FAILURE(status)) {
                    // delete the mapping
                    result = NULL;
                    delete tmpResult;
                } else {
                    result = tmpResult;
                }
            }
        } else {
            // another thread already put the one
            delete tmpResult;
        }
    }
    umtx_unlock(&gZoneMetaLock);

    return result;
}
Example #6
0
const UChar* U_EXPORT2
ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) {
    if (U_FAILURE(status)) {
        return NULL;
    }

    int32_t len = tzid.length();
    if (len > ZID_KEY_MAX) {
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return NULL;
    }

    // Checking the cached results
    UBool initialized;
    UMTX_CHECK(&gZoneMetaLock, gCanonicalIDCacheInitialized, initialized);
    if (!initialized) {
        // Create empty hashtable
        umtx_lock(&gZoneMetaLock);
        {
            if (!gCanonicalIDCacheInitialized) {
                gCanonicalIDCache = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
                if (gCanonicalIDCache == NULL) {
                    status = U_MEMORY_ALLOCATION_ERROR;
                }
                if (U_FAILURE(status)) {
                    gCanonicalIDCache = NULL;
                    return NULL;
                }
                // No key/value deleters - keys/values are from a resource bundle
                gCanonicalIDCacheInitialized = TRUE;
                ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
            }
        }
        umtx_unlock(&gZoneMetaLock);
    }

    const UChar *canonicalID = NULL;

    UErrorCode tmpStatus = U_ZERO_ERROR;
    UChar utzid[ZID_KEY_MAX + 1];
    tzid.extract(utzid, ZID_KEY_MAX + 1, tmpStatus);
    U_ASSERT(tmpStatus == U_ZERO_ERROR);    // we checked the length of tzid already

    // Check if it was already cached
    umtx_lock(&gZoneMetaLock);
    {
        canonicalID = (const UChar *)uhash_get(gCanonicalIDCache, utzid);
    }
    umtx_unlock(&gZoneMetaLock);

    if (canonicalID != NULL) {
        return canonicalID;
    }

    // If not, resolve CLDR canonical ID with resource data
    UBool isInputCanonical = FALSE;
    char id[ZID_KEY_MAX + 1];
    const UChar* idChars = tzid.getBuffer();

    u_UCharsToChars(idChars,id,len);
    id[len] = (char) 0; // Make sure it is null terminated.

    // replace '/' with ':'
    char *p = id;
    while (*p++) {
        if (*p == '/') {
            *p = ':';
        }
    }

    UResourceBundle *top = ures_openDirect(NULL, gTimeZoneTypes, &tmpStatus);
    UResourceBundle *rb = ures_getByKey(top, gTypeMapTag, NULL, &tmpStatus);
    ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus);
    ures_getByKey(rb, id, rb, &tmpStatus);
    if (U_SUCCESS(tmpStatus)) {
        // type entry (canonical) found
        // the input is the canonical ID. resolve to const UChar*
        canonicalID = TimeZone::findID(tzid);
        isInputCanonical = TRUE;
    }

    if (canonicalID == NULL) {
        // If a map element not found, then look for an alias
        tmpStatus = U_ZERO_ERROR;
        ures_getByKey(top, gTypeAliasTag, rb, &tmpStatus);
        ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus);
        const UChar *canonical = ures_getStringByKey(rb,id,NULL,&tmpStatus);
        if (U_SUCCESS(tmpStatus)) {
            // canonical map found
            canonicalID = canonical;
        }

        if (canonicalID == NULL) {
            // Dereference the input ID using the tz data
            const UChar *derefer = TimeZone::dereferOlsonLink(tzid);
            if (derefer == NULL) {
                status = U_ILLEGAL_ARGUMENT_ERROR;
            } else {
                len = u_strlen(derefer);
                u_UCharsToChars(derefer,id,len);
                id[len] = (char) 0; // Make sure it is null terminated.

                // replace '/' with ':'
                char *p = id;
                while (*p++) {
                    if (*p == '/') {
                        *p = ':';
                    }
                }

                // If a dereference turned something up then look for an alias.
                // rb still points to the alias table, so we don't have to go looking
                // for it.
                tmpStatus = U_ZERO_ERROR;
                canonical = ures_getStringByKey(rb,id,NULL,&tmpStatus);
                if (U_SUCCESS(tmpStatus)) {
                    // canonical map for the dereferenced ID found
                    canonicalID = canonical;
                } else {
                    canonicalID = derefer;
                    isInputCanonical = TRUE;
                }
            }
        }
    }
    ures_close(rb);
    ures_close(top);

    if (U_SUCCESS(status)) {
        U_ASSERT(canonicalID != NULL);  // canocanilD must be non-NULL here

        // Put the resolved canonical ID to the cache
        umtx_lock(&gZoneMetaLock);
        {
            const UChar* idInCache = (const UChar *)uhash_get(gCanonicalIDCache, utzid);
            if (idInCache == NULL) {
                const UChar* key = ZoneMeta::findTimeZoneID(tzid);
                U_ASSERT(key != NULL);
                if (key != NULL) {
                    idInCache = (const UChar *)uhash_put(gCanonicalIDCache, (void *)key, (void *)canonicalID, &status);
                    U_ASSERT(idInCache == NULL);
                }
            }
            if (U_SUCCESS(status) && isInputCanonical) {
                // Also put canonical ID itself into the cache if not exist
                const UChar *canonicalInCache = (const UChar*)uhash_get(gCanonicalIDCache, canonicalID);
                if (canonicalInCache == NULL) {
                    canonicalInCache = (const UChar *)uhash_put(gCanonicalIDCache, (void *)canonicalID, (void *)canonicalID, &status);
                    U_ASSERT(canonicalInCache == NULL);
                }
            }
        }
        umtx_unlock(&gZoneMetaLock);
    }

    return canonicalID;
}
Example #7
0
static int32_t
unorm_iterate(UCharIterator * src, UBool forward,
              UChar * dest, int32_t destCapacity,
              UNormalizationMode mode, int32_t options,
              UBool doNormalize, UBool * pNeededToNormalize,
              UErrorCode * pErrorCode)
{
	const Normalizer2 * n2 = Normalizer2Factory::getInstance(mode, *pErrorCode);
	const UnicodeSet * uni32;
	if (options & UNORM_UNICODE_3_2)
	{
		uni32 = uniset_getUnicode32Instance(*pErrorCode);
	}
	else
	{
		uni32 = NULL; // unused
	}
	FilteredNormalizer2 fn2(*n2, *uni32);
	if (options & UNORM_UNICODE_3_2)
	{
		n2 = &fn2;
	}
	if (U_FAILURE(*pErrorCode))
	{
		return 0;
	}
	if (destCapacity < 0 || (dest == NULL && destCapacity > 0) ||
	    src == NULL
	   )
	{
		*pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
		return 0;
	}

	if (pNeededToNormalize != NULL)
	{
		*pNeededToNormalize = FALSE;
	}
	if (!(forward ? src->hasNext(src) : src->hasPrevious(src)))
	{
		return u_terminateUChars(dest, destCapacity, 0, pErrorCode);
	}

	UnicodeString buffer;
	UChar32 c;
	if (forward)
	{
		/* get one character and ignore its properties */
		buffer.append(uiter_next32(src));
		/* get all following characters until we see a boundary */
		while ((c = uiter_next32(src)) >= 0)
		{
			if (n2->hasBoundaryBefore(c))
			{
				/* back out the latest movement to stop at the boundary */
				src->move(src, -U16_LENGTH(c), UITER_CURRENT);
				break;
			}
			else
			{
				buffer.append(c);
			}
		}
	}
	else
	{
		while ((c = uiter_previous32(src)) >= 0)
		{
			/* always write this character to the front of the buffer */
			buffer.insert(0, c);
			/* stop if this just-copied character is a boundary */
			if (n2->hasBoundaryBefore(c))
			{
				break;
			}
		}
	}

	UnicodeString destString(dest, 0, destCapacity);
	if (buffer.length() > 0 && doNormalize)
	{
		n2->normalize(buffer, destString, *pErrorCode).extract(dest, destCapacity, *pErrorCode);
		if (pNeededToNormalize != NULL && U_SUCCESS(*pErrorCode))
		{
			*pNeededToNormalize = destString != buffer;
		}
		return destString.length();
	}
	else
	{
		/* just copy the source characters */
		return buffer.extract(dest, destCapacity, *pErrorCode);
	}
}