/** * Given an ID, open the appropriate resource for the given time zone. * Dereference aliases if necessary. * @param id zone id * @param res resource, which must be ready for use (initialized but not open) * @param ec input-output error code * @return top-level resource bundle */ static UResourceBundle* openOlsonResource(const UnicodeString& id, UResourceBundle& res, UErrorCode& ec) { #if U_DEBUG_TZ char buf[128]; id.extract(0, sizeof(buf)-1, buf, sizeof(buf), ""); #endif UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec); U_DEBUG_TZ_MSG(("pre: res sz=%d\n", ures_getSize(&res))); /* &res = */ getZoneByName(top, id, &res, ec); // Dereference if this is an alias. Docs say result should be 1 // but it is 0 in 2.8 (?). U_DEBUG_TZ_MSG(("Loading zone '%s' (%s, size %d) - %s\n", buf, ures_getKey((UResourceBundle*)&res), ures_getSize(&res), u_errorName(ec))); if (ures_getType(&res) == URES_INT && getOlsonMeta(top)) { int32_t deref = ures_getInt(&res, &ec) + 0; U_DEBUG_TZ_MSG(("getInt: %s - type is %d\n", u_errorName(ec), ures_getType(&res))); UResourceBundle *ares = ures_getByKey(top, kZONES, NULL, &ec); // dereference Zones section ures_getByIndex(ares, deref, &res, &ec); ures_close(ares); U_DEBUG_TZ_MSG(("alias to #%d (%s) - %s\n", deref, "??", u_errorName(ec))); } else { U_DEBUG_TZ_MSG(("not an alias - size %d\n", ures_getSize(&res))); } U_DEBUG_TZ_MSG(("%s - final status is %s\n", buf, u_errorName(ec))); return top; }
const UChar* TimeZone::dereferOlsonLink(const UnicodeString& id) { const UChar *result = NULL; UErrorCode ec = U_ZERO_ERROR; UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &ec); // resolve zone index by name UResourceBundle *names = ures_getByKey(rb, kNAMES, NULL, &ec); int32_t idx = findInStringArray(names, id, ec); result = ures_getStringByIndex(names, idx, NULL, &ec); // open the zone bundle by index ures_getByKey(rb, kZONES, rb, &ec); ures_getByIndex(rb, idx, rb, &ec); if (U_SUCCESS(ec)) { if (ures_getType(rb) == URES_INT) { // this is a link - dereference the link int32_t deref = ures_getInt(rb, &ec); const UChar* tmp = ures_getStringByIndex(names, deref, NULL, &ec); if (U_SUCCESS(ec)) { result = tmp; } } } ures_close(names); ures_close(rb); return result; }
/* {{{ resourcebundle_get_iterator */ zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref ) { ResourceBundle_object *rb = Z_INTL_RESOURCEBUNDLE_P(object ); ResourceBundle_iterator *iterator = emalloc( sizeof( ResourceBundle_iterator ) ); if (byref) { php_error( E_ERROR, "ResourceBundle does not support writable iterators" ); } zend_iterator_init(&iterator->intern); ZVAL_COPY(&iterator->intern.data, object); iterator->intern.funcs = &resourcebundle_iterator_funcs; iterator->subject = rb; /* The iterated rb can only be either URES_TABLE or URES_ARRAY * All other types are returned as php primitives! */ iterator->is_table = (ures_getType( rb->me ) == URES_TABLE); iterator->length = ures_getSize( rb->me ); ZVAL_UNDEF(&iterator->current); iterator->currentkey = NULL; iterator->i = 0; return (zend_object_iterator *) iterator; }
TZEnumeration(const char* country) : map(NULL), len(0), pos(0) { if (!getOlsonMeta()) { return; } UErrorCode ec = U_ZERO_ERROR; UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec); ures_getByKey(res, kREGIONS, res, &ec); if (U_SUCCESS(ec) && ures_getType(res) == URES_ARRAY) { UChar uCountry[] = {0, 0, 0, 0}; if (country) { u_charsToUChars(country, uCountry, 2); } else { u_strcpy(uCountry, WORLD); } // count matches int32_t count = 0; int32_t i; const UChar *region; for (i = 0; i < ures_getSize(res); i++) { region = ures_getStringByIndex(res, i, NULL, &ec); if (U_FAILURE(ec)) { break; } if (u_strcmp(uCountry, region) == 0) { count++; } } if (count > 0) { map = (int32_t*)uprv_malloc(sizeof(int32_t) * count); if (map != NULL) { int32_t idx = 0; for (i = 0; i < ures_getSize(res); i++) { region = ures_getStringByIndex(res, i, NULL, &ec); if (U_FAILURE(ec)) { break; } if (u_strcmp(uCountry, region) == 0) { map[idx++] = i; } } if (U_SUCCESS(ec)) { len = count; } else { uprv_free(map); map = NULL; } } else { U_DEBUG_TZ_MSG(("Failed to load tz for region %s: %s\n", country, u_errorName(ec))); } } } ures_close(res); }
/* {{{ ResourceBundle_extract_value */ void resourcebundle_extract_value( zval *return_value, ResourceBundle_object *source ) { UResType restype; const UChar* ufield; const uint8_t* bfield; const int32_t* vfield; int32_t ilen; int i; zend_long lfield; ResourceBundle_object* newrb; restype = ures_getType( source->child ); switch (restype) { case URES_STRING: ufield = ures_getString( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve string value"); INTL_METHOD_RETVAL_UTF8(source, (UChar *)ufield, ilen, 0); break; case URES_BINARY: bfield = ures_getBinary( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve binary value"); ZVAL_STRINGL( return_value, (char *) bfield, ilen ); break; case URES_INT: lfield = ures_getInt( source->child, &INTL_DATA_ERROR_CODE(source) ); INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve integer value"); ZVAL_LONG( return_value, lfield ); break; case URES_INT_VECTOR: vfield = ures_getIntVector( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve vector value"); array_init( return_value ); for (i=0; i<ilen; i++) { add_next_index_long( return_value, vfield[i] ); } break; case URES_ARRAY: case URES_TABLE: object_init_ex( return_value, ResourceBundle_ce_ptr ); newrb = Z_INTL_RESOURCEBUNDLE_P(return_value); newrb->me = source->child; source->child = NULL; intl_errors_reset(INTL_DATA_ERROR_P(source)); break; default: intl_errors_set(INTL_DATA_ERROR_P(source), U_ILLEGAL_ARGUMENT_ERROR, "Unknown resource type", 0); RETURN_FALSE; break; } }
static void printOutBundle(FILE *out, UConverter *converter, UResourceBundle *resource, int32_t indent, const char *pname, UErrorCode *status) { static const UChar cr[] = { '\n' }; /* int32_t noOfElements = ures_getSize(resource);*/ int32_t i = 0; const char *key = ures_getKey(resource); switch(ures_getType(resource)) { case RES_STRING : { int32_t len=0; const UChar* thestr = ures_getString(resource, &len, status); UChar *string = quotedString(thestr); /* TODO: String truncation */ if(trunc && len > truncsize) { char msg[128]; printIndent(out, converter, indent); sprintf(msg, "// WARNING: this resource, size %li is truncated to %li\n", (long)len, (long)(truncsize/2)); printCString(out, converter, msg, -1); len = truncsize/2; } printIndent(out, converter, indent); if(key != NULL) { static const UChar openStr[] = { 0x0020, 0x007B, 0x0020, 0x0022 }; /* " { \"" */ static const UChar closeStr[] = { 0x0022, 0x0020, 0x007D }; /* "\" }" */ printCString(out, converter, key, (int32_t)uprv_strlen(key)); printString(out, converter, openStr, (int32_t)(sizeof(openStr)/sizeof(*openStr))); printString(out, converter, string, len); printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); } else { static const UChar openStr[] = { 0x0022 }; /* "\"" */ static const UChar closeStr[] = { 0x0022, 0x002C }; /* "\"," */ printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); printString(out, converter, string, (int32_t)(u_strlen(string))); printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); } if(verbose) { printCString(out, converter, "// STRING", -1); } printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); uprv_free(string); } break; case RES_INT : { static const UChar openStr[] = { 0x003A, 0x0069, 0x006E, 0x0074, 0x0020, 0x007B, 0x0020 }; /* ":int { " */ static const UChar closeStr[] = { 0x0020, 0x007D }; /* " }" */ UChar num[20]; printIndent(out, converter, indent); if(key != NULL) { printCString(out, converter, key, -1); } printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); uprv_itou(num, 20, ures_getInt(resource, status), 10, 0); printString(out, converter, num, u_strlen(num)); printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); if(verbose) { printCString(out, converter, "// INT", -1); } printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); break; } case RES_BINARY : { int32_t len = 0; const int8_t *data = (const int8_t *)ures_getBinary(resource, &len, status); if(trunc && len > truncsize) { char msg[128]; printIndent(out, converter, indent); sprintf(msg, "// WARNING: this resource, size %li is truncated to %li\n", (long)len, (long)(truncsize/2)); printCString(out, converter, msg, -1); len = truncsize; } if(U_SUCCESS(*status)) { static const UChar openStr[] = { 0x003A, 0x0062, 0x0069, 0x006E, 0x0061, 0x0072, 0x0079, 0x0020, 0x007B, 0x0020 }; /* ":binary { " */ static const UChar closeStr[] = { 0x0020, 0x007D, 0x0020 }; /* " } " */ printIndent(out, converter, indent); if(key != NULL) { printCString(out, converter, key, -1); } printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); for(i = 0; i<len; i++) { printHex(out, converter, *data++); } printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); if(verbose) { printCString(out, converter, " // BINARY", -1); } printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); } else { reportError(pname, status, "getting binary value"); } } break; case RES_INT_VECTOR : { int32_t len = 0; const int32_t *data = ures_getIntVector(resource, &len, status); if(U_SUCCESS(*status)) { static const UChar openStr[] = { 0x003A, 0x0069, 0x006E, 0x0074, 0x0076, 0x0065, 0x0063, 0x0074, 0x006F, 0x0072, 0x0020, 0x007B, 0x0020 }; /* ":intvector { " */ static const UChar closeStr[] = { 0x0020, 0x007D, 0x0020 }; /* " } " */ UChar num[20]; printIndent(out, converter, indent); if(key != NULL) { printCString(out, converter, key, -1); } printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); for(i = 0; i < len - 1; i++) { int32_t numLen = uprv_itou(num, 20, data[i], 10, 0); num[numLen++] = 0x002C; /* ',' */ num[numLen++] = 0x0020; /* ' ' */ num[numLen] = 0; printString(out, converter, num, u_strlen(num)); } if(len > 0) { uprv_itou(num, 20, data[len - 1], 10, 0); printString(out, converter, num, u_strlen(num)); } printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); if(verbose) { printCString(out, converter, "// INTVECTOR", -1); } printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); } else { reportError(pname, status, "getting int vector"); } } break; case RES_TABLE : case RES_ARRAY : { static const UChar openStr[] = { 0x007B }; /* "{" */ static const UChar closeStr[] = { 0x007D, '\n' }; /* "}\n" */ UResourceBundle *t = NULL; ures_resetIterator(resource); printIndent(out, converter, indent); if(key != NULL) { printCString(out, converter, key, -1); } printString(out, converter, openStr, (int32_t)(sizeof(openStr) / sizeof(*openStr))); if(verbose) { if(ures_getType(resource) == RES_TABLE) { printCString(out, converter, "// TABLE", -1); } else { printCString(out, converter, "// ARRAY", -1); } } printString(out, converter, cr, (int32_t)(sizeof(cr) / sizeof(*cr))); if(suppressAliases == FALSE) { while(U_SUCCESS(*status) && ures_hasNext(resource)) { t = ures_getNextResource(resource, t, status); if(U_SUCCESS(*status)) { printOutBundle(out, converter, t, indent+indentsize, pname, status); } else { reportError(pname, status, "While processing table"); *status = U_ZERO_ERROR; } } } else { /* we have to use low level access to do this */ Resource r = RES_BOGUS; for(i = 0; i < ures_getSize(resource); i++) { /* need to know if it's an alias */ if(ures_getType(resource) == RES_TABLE) { r = derb_getTableItem(resource->fResData.pRoot, resource->fRes, (int16_t)i); key = derb_getTableKey(resource->fResData.pRoot, resource->fRes, (int16_t)i); } else { r = derb_getArrayItem(resource->fResData.pRoot, resource->fRes, i); } if(U_SUCCESS(*status)) { if(RES_GET_TYPE(r) == RES_ALIAS) { printOutAlias(out, converter, resource, r, key, indent+indentsize, pname, status); } else { t = ures_getByIndex(resource, i, t, status); printOutBundle(out, converter, t, indent+indentsize, pname, status); } } else { reportError(pname, status, "While processing table"); *status = U_ZERO_ERROR; } } } printIndent(out, converter, indent); printString(out, converter, closeStr, (int32_t)(sizeof(closeStr) / sizeof(*closeStr))); ures_close(t); } break; default: break; } }
static void TestTable32(void) { static const struct { const char *key; int32_t number; } testcases[]={ { "ooooooooooooooooo", 0 }, { "oooooooooooooooo1", 1 }, { "ooooooooooooooo1o", 2 }, { "oo11ooo1ooo11111o", 25150 }, { "oo11ooo1ooo111111", 25151 }, { "o1111111111111111", 65535 }, { "1oooooooooooooooo", 65536 }, { "1ooooooo11o11ooo1", 65969 }, { "1ooooooo11o11oo1o", 65970 }, { "1ooooooo111oo1111", 65999 } }; /* ### TODO UResourceBundle staticItem={ 0 }; - need to know the size */ UResourceBundle *res, *item; const UChar *s; const char *key; UErrorCode errorCode; int32_t i, j, number, parsedNumber, length, count; errorCode=U_ZERO_ERROR; res=ures_open(loadTestData(&errorCode), "testtable32", &errorCode); if(U_FAILURE(errorCode)) { log_data_err("unable to open testdata/testtable32.res - %s\n", u_errorName(errorCode)); return; } if(ures_getType(res)!=URES_TABLE) { log_data_err("testdata/testtable32.res has type %d instead of URES_TABLE\n", ures_getType(res)); } count=ures_getSize(res); if(count!=66000) { log_err("testdata/testtable32.res should have 66000 entries but has %d\n", count); } /* get the items by index */ item=NULL; for(i=0; i<count; ++i) { item=ures_getByIndex(res, i, item, &errorCode); if(U_FAILURE(errorCode)) { log_err("unable to get item %d of %d in testdata/testtable32.res - %s\n", i, count, u_errorName(errorCode)); break; } key=ures_getKey(item); parsedNumber=parseTable32Key(key); switch(ures_getType(item)) { case URES_STRING: s=ures_getString(item, &length, &errorCode); if(U_FAILURE(errorCode) || s==NULL) { log_err("unable to access the string \"%s\" at %d in testdata/testtable32.res - %s\n", key, i, u_errorName(errorCode)); number=-1; } else { j=0; U16_NEXT(s, j, length, number); } break; case URES_INT: number=ures_getInt(item, &errorCode); if(U_FAILURE(errorCode)) { log_err("unable to access the integer \"%s\" at %d in testdata/testtable32.res - %s\n", key, i, u_errorName(errorCode)); number=-1; } break; default: log_err("unexpected resource type %d for \"%s\" at %d in testdata/testtable32.res - %s\n", ures_getType(item), key, i, u_errorName(errorCode)); number=-1; break; } if(number>=0 && number!=parsedNumber) { log_err("\"%s\" at %d in testdata/testtable32.res has a string/int value of %d, expected %d\n", key, i, number, parsedNumber); } } /* search for some items by key */ for(i=0; i<UPRV_LENGTHOF(testcases); ++i) { item=ures_getByKey(res, testcases[i].key, item, &errorCode); if(U_FAILURE(errorCode)) { log_err("unable to find the key \"%s\" in testdata/testtable32.res - %s\n", testcases[i].key, u_errorName(errorCode)); continue; } switch(ures_getType(item)) { case URES_STRING: s=ures_getString(item, &length, &errorCode); if(U_FAILURE(errorCode) || s==NULL) { log_err("unable to access the string \"%s\" in testdata/testtable32.res - %s\n", testcases[i].key, u_errorName(errorCode)); number=-1; } else { j=0; U16_NEXT(s, j, length, number); } break; case URES_INT: number=ures_getInt(item, &errorCode); if(U_FAILURE(errorCode)) { log_err("unable to access the integer \"%s\" in testdata/testtable32.res - %s\n", testcases[i].key, u_errorName(errorCode)); number=-1; } break; default: log_err("unexpected resource type %d for \"%s\" in testdata/testtable32.res - %s\n", ures_getType(item), testcases[i].key, u_errorName(errorCode)); number=-1; break; } if(number>=0 && number!=testcases[i].number) { log_err("\"%s\" in testdata/testtable32.res has a string/int value of %d, expected %d\n", testcases[i].key, number, testcases[i].number); } key=ures_getKey(item); if(0!=uprv_strcmp(key, testcases[i].key)) { log_err("\"%s\" in testdata/testtable32.res claims to have the key \"%s\"\n", testcases[i].key, key); } } ures_close(item); ures_close(res); }
#include "intl_data.h" #include "resourcebundle/resourcebundle_class.h" /* {{{ ResourceBundle_extract_value */ void resourcebundle_extract_value( zval *return_value, ResourceBundle_object *source TSRMLS_DC ) { UResType restype; const UChar* ufield; const uint8_t* bfield; const int32_t* vfield; int32_t ilen; int i; long lfield; ResourceBundle_object* newrb; restype = ures_getType( source->child ); switch (restype) { case URES_STRING: ufield = ures_getString( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve string value"); INTL_METHOD_RETVAL_UTF8(source, (UChar *)ufield, ilen, 0); break; case URES_BINARY: bfield = ures_getBinary( source->child, &ilen, &INTL_DATA_ERROR_CODE(source) ); INTL_METHOD_CHECK_STATUS(source, "Failed to retrieve binary value"); ZVAL_STRINGL( return_value, (char *) bfield, ilen ); break; case URES_INT:
void printOutBundle(UFILE *out, UResourceBundle *resource, int32_t indent, UErrorCode *status) { int32_t i = 0; const char *key = ures_getKey(resource); switch(ures_getType(resource)) { case URES_STRING : { int32_t len=0; const UChar*thestr = ures_getString(resource, &len, status); UChar *string = quotedString(thestr); /* TODO: String truncation */ /* if(trunc && len > truncsize) { printIndent(out, indent); u_fprintf(out, "// WARNING: this string, size %d is truncated to %d\n", len, truncsize/2); len = truncsize/2; } */ printIndent(out, indent); if(key != NULL) { u_fprintf(out, "%s { \"%S\" } ", key, string); } else { u_fprintf(out, "\"%S\",", string); } if(VERBOSE) { u_fprintf(out, " // STRING"); } u_fprintf(out, "\n"); free(string); } break; case URES_INT : printIndent(out, indent); if(key != NULL) { u_fprintf(out, "%s", key); } u_fprintf(out, ":int { %li } ", ures_getInt(resource, status)); if(VERBOSE) { u_fprintf(out, " // INT"); } u_fprintf(out, "\n"); break; case URES_BINARY : { int32_t len = 0; const int8_t *data = (const int8_t *)ures_getBinary(resource, &len, status); if(trunc && len > truncsize) { printIndent(out, indent); u_fprintf(out, "// WARNING: this resource, size %li is truncated to %li\n", len, truncsize/2); len = truncsize/2; } if(U_SUCCESS(*status)) { printIndent(out, indent); if(key != NULL) { u_fprintf(out, "%s", key); } u_fprintf(out, ":binary { "); for(i = 0; i<len; i++) { printHex(out, data++); } u_fprintf(out, " }"); if(VERBOSE) { u_fprintf(out, " // BINARY"); } u_fprintf(out, "\n"); } else { reportError(status); } } break; case URES_INT_VECTOR : { int32_t len = 0; const int32_t *data = ures_getIntVector(resource, &len, status); if(U_SUCCESS(*status)) { printIndent(out, indent); if(key != NULL) { u_fprintf(out, "%s", key); } u_fprintf(out, ":intvector { "); for(i = 0; i<len-1; i++) { u_fprintf(out, "%d, ", data[i]); } if(len > 0) { u_fprintf(out, "%d ", data[len-1]); } u_fprintf(out, "}"); if(VERBOSE) { u_fprintf(out, " // INTVECTOR"); } u_fprintf(out, "\n"); } else { reportError(status); } } break; case URES_TABLE : case URES_ARRAY : { UResourceBundle *t = NULL; ures_resetIterator(resource); printIndent(out, indent); if(key != NULL) { u_fprintf(out, "%s ", key); } u_fprintf(out, "{"); if(VERBOSE) { if(ures_getType(resource) == URES_TABLE) { u_fprintf(out, " // TABLE"); } else { u_fprintf(out, " // ARRAY"); } } u_fprintf(out, "\n"); while(ures_hasNext(resource)) { t = ures_getNextResource(resource, t, status); printOutBundle(out, t, indent+indentsize, status); } printIndent(out, indent); u_fprintf(out, "}\n"); ures_close(t); } break; default: break; } }
void NewResourceBundleTest::TestOtherAPI(){ UErrorCode err = U_ZERO_ERROR; const char* testdatapath=loadTestData(err); UnicodeString tDataPathUS = UnicodeString(testdatapath, ""); if(U_FAILURE(err)) { dataerrln("Could not load testdata.dat %s " + UnicodeString(u_errorName(err))); return; } /* Make sure that users using te_IN for the default locale don't get test failures. */ Locale originalDefault; if (Locale::getDefault() == Locale("te_IN")) { Locale::setDefault(Locale("en_US"), err); } Locale *locale=new Locale("te_IN"); ResourceBundle test0(tDataPathUS, *locale, err); if(U_FAILURE(err)){ errln("Construction failed"); return; } ResourceBundle test1(testdatapath, *locale, err); if(U_FAILURE(err)){ errln("Construction failed"); return; } logln("Testing getLocale()\n"); if(strcmp(test1.getLocale().getName(), locale->getName()) !=0 ){ errln("FAIL: ResourceBundle::getLocale() failed\n"); } delete locale; logln("Testing ResourceBundle(UErrorCode)\n"); ResourceBundle defaultresource(err); ResourceBundle explicitdefaultresource(NULL, Locale::getDefault(), err); if(U_FAILURE(err)){ errcheckln(err, "Construction of default resourcebundle failed - %s", u_errorName(err)); return; } // You can't compare the default locale to the resolved locale in the // resource bundle due to aliasing, keywords in the default locale // or the chance that the machine running these tests is using a locale // that isn't available in ICU. if(strcmp(defaultresource.getLocale().getName(), explicitdefaultresource.getLocale().getName()) != 0){ errln("Construction of default resourcebundle didn't take the defaultlocale. Expected %s Got %s err=%s\n", explicitdefaultresource.getLocale().getName(), defaultresource.getLocale().getName(), u_errorName(err)); } ResourceBundle copyRes(defaultresource); if(strcmp(copyRes.getName(), defaultresource.getName() ) !=0 || strcmp(test1.getName(), defaultresource.getName() ) ==0 || strcmp(copyRes.getLocale().getName(), defaultresource.getLocale().getName() ) !=0 || strcmp(test1.getLocale().getName(), defaultresource.getLocale().getName() ) ==0 ) { errln("copy construction failed\n"); } ResourceBundle defaultSub = defaultresource.get((int32_t)0, err); ResourceBundle defSubCopy(defaultSub); if(strcmp(defSubCopy.getName(), defaultSub.getName() ) !=0 || strcmp(defSubCopy.getLocale().getName(), defaultSub.getLocale().getName() ) !=0 ){ errln("copy construction for subresource failed\n"); } ResourceBundle *p; p = defaultresource.clone(); if(p == &defaultresource || !equalRB(*p, defaultresource)) { errln("ResourceBundle.clone() failed"); } delete p; p = defaultSub.clone(); if(p == &defaultSub || !equalRB(*p, defaultSub)) { errln("2nd ResourceBundle.clone() failed"); } delete p; UVersionInfo ver; copyRes.getVersion(ver); logln("Version returned: [%d.%d.%d.%d]\n", ver[0], ver[1], ver[2], ver[3]); logln("Testing C like UnicodeString APIs\n"); UResourceBundle *testCAPI = NULL, *bundle = NULL, *rowbundle = NULL, *temp = NULL; err = U_ZERO_ERROR; const char* data[]={ "string_in_Root_te_te_IN", "1", "array_in_Root_te_te_IN", "5", "array_2d_in_Root_te_te_IN", "4", }; testCAPI = ures_open(testdatapath, "te_IN", &err); if(U_SUCCESS(err)) { // Do the testing // first iteration uint32_t i; int32_t count, row=0, col=0; char buf[5]; UnicodeString expected; UnicodeString element("TE_IN"); UnicodeString action; for(i=0; i<UPRV_LENGTHOF(data); i=i+2){ action = "te_IN"; action +=".get("; action += data[i]; action +=", err)"; err=U_ZERO_ERROR; bundle = ures_getByKey(testCAPI, data[i], bundle, &err); if(!U_FAILURE(err)){ const char* key = NULL; action = "te_IN"; action +=".getKey()"; CONFIRM_EQ((UnicodeString)ures_getKey(bundle), (UnicodeString)data[i]); count=0; row=0; while(ures_hasNext(bundle)){ action = data[i]; action +=".getNextString(err)"; row=count; UnicodeString got=ures_getNextUnicodeString(bundle, &key, &err); if(U_SUCCESS(err)){ expected=element; if(ures_getSize(bundle) > 1){ CONFIRM_EQ(ures_getType(bundle), URES_ARRAY); expected+=itoa(row, buf); rowbundle=ures_getByIndex(bundle, row, rowbundle, &err); if(!U_FAILURE(err) && ures_getSize(rowbundle)>1){ col=0; while(ures_hasNext(rowbundle)){ expected=element; got=ures_getNextUnicodeString(rowbundle, &key, &err); temp = ures_getByIndex(rowbundle, col, temp, &err); UnicodeString bla = ures_getUnicodeString(temp, &err); UnicodeString bla2 = ures_getUnicodeStringByIndex(rowbundle, col, &err); if(!U_FAILURE(err)){ expected+=itoa(row, buf); expected+=itoa(col, buf); col++; CONFIRM_EQ(got, expected); CONFIRM_EQ(bla, expected); CONFIRM_EQ(bla2, expected); } } CONFIRM_EQ(col, ures_getSize(rowbundle)); } } else{ CONFIRM_EQ(ures_getType(bundle), (int32_t)URES_STRING); } } CONFIRM_EQ(got, expected); count++; } } } // Check that ures_getUnicodeString() & variants return a bogus string if failure. // Same relevant code path whether the failure code is passed in // or comes from a lookup error. UErrorCode failure = U_INTERNAL_PROGRAM_ERROR; assertTrue("ures_getUnicodeString(failure).isBogus()", ures_getUnicodeString(testCAPI, &failure).isBogus()); assertTrue("ures_getNextUnicodeString(failure).isBogus()", ures_getNextUnicodeString(testCAPI, NULL, &failure).isBogus()); assertTrue("ures_getUnicodeStringByIndex(failure).isBogus()", ures_getUnicodeStringByIndex(testCAPI, 999, &failure).isBogus()); assertTrue("ures_getUnicodeStringByKey(failure).isBogus()", ures_getUnicodeStringByKey(testCAPI, "bogus key", &failure).isBogus()); ures_close(temp); ures_close(rowbundle); ures_close(bundle); ures_close(testCAPI); } else { errln("failed to open a resource bundle\n"); } /* Restore the default locale for the other tests. */ Locale::setDefault(originalDefault, err); }
UResType ResourceBundle::getType(void) const { return ures_getType(fResource); }
static UResourceBundle* getZoneByName(const UResourceBundle* top, const UnicodeString& id, UResourceBundle *oldbundle, UErrorCode& status) { // load the Rules object UResourceBundle *tmp = ures_getByKey(top, kNAMES, NULL, &status); // search for the string int32_t idx = findInStringArray(tmp, id, status); if((idx == -1) && U_SUCCESS(status)) { // not found status = U_MISSING_RESOURCE_ERROR; //ures_close(oldbundle); //oldbundle = NULL; } else { U_DEBUG_TZ_MSG(("gzbn: oldbundle= size %d, type %d, %s\n", ures_getSize(tmp), ures_getType(tmp), u_errorName(status))); tmp = ures_getByKey(top, kZONES, tmp, &status); // get Zones object from top U_DEBUG_TZ_MSG(("gzbn: loaded ZONES, size %d, type %d, path %s %s\n", ures_getSize(tmp), ures_getType(tmp), ures_getPath(tmp), u_errorName(status))); oldbundle = ures_getByIndex(tmp, idx, oldbundle, &status); // get nth Zone object U_DEBUG_TZ_MSG(("gzbn: loaded z#%d, size %d, type %d, path %s, %s\n", idx, ures_getSize(oldbundle), ures_getType(oldbundle), ures_getPath(oldbundle), u_errorName(status))); } ures_close(tmp); if(U_FAILURE(status)) { //ures_close(oldbundle); return NULL; } else { return oldbundle; } }
/* * Initializes the region data from the ICU resource bundles. The region data * contains the basic relationships such as which regions are known, what the numeric * codes are, any known aliases, and the territory containment data. * * If the region data has already loaded, then this method simply returns without doing * anything meaningful. */ void Region::loadRegionData() { if (regionDataIsLoaded) { return; } umtx_lock(&gRegionDataLock); if (regionDataIsLoaded) { // In case another thread gets to it before we do... umtx_unlock(&gRegionDataLock); return; } UErrorCode status = U_ZERO_ERROR; UResourceBundle* regionCodes = NULL; UResourceBundle* territoryAlias = NULL; UResourceBundle* codeMappings = NULL; UResourceBundle* worldContainment = NULL; UResourceBundle* territoryContainment = NULL; UResourceBundle* groupingContainment = NULL; DecimalFormat *df = new DecimalFormat(status); df->setParseIntegerOnly(TRUE); regionIDMap = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status); uhash_setValueDeleter(regionIDMap, deleteRegion); numericCodeMap = uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status); regionAliases = uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status); uhash_setKeyDeleter(regionAliases,uprv_deleteUObject); UResourceBundle *rb = ures_openDirect(NULL,"metadata",&status); regionCodes = ures_getByKey(rb,"regionCodes",NULL,&status); territoryAlias = ures_getByKey(rb,"territoryAlias",NULL,&status); UResourceBundle *rb2 = ures_openDirect(NULL,"supplementalData",&status); codeMappings = ures_getByKey(rb2,"codeMappings",NULL,&status); territoryContainment = ures_getByKey(rb2,"territoryContainment",NULL,&status); worldContainment = ures_getByKey(territoryContainment,"001",NULL,&status); groupingContainment = ures_getByKey(territoryContainment,"grouping",NULL,&status); UVector *continents = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); while ( ures_hasNext(worldContainment) ) { UnicodeString *continentName = new UnicodeString(ures_getNextUnicodeString(worldContainment,NULL,&status)); continents->addElement(continentName,status); } UVector *groupings = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); while ( ures_hasNext(groupingContainment) ) { UnicodeString *groupingName = new UnicodeString(ures_getNextUnicodeString(groupingContainment,NULL,&status)); groupings->addElement(groupingName,status); } while ( ures_hasNext(regionCodes) ) { UnicodeString regionID = ures_getNextUnicodeString(regionCodes,NULL,&status); Region *r = new Region(); r->idStr = regionID; r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV); r->type = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known. uhash_put(regionIDMap,(void *)&(r->idStr),(void *)r,&status); Formattable result; UErrorCode ps = U_ZERO_ERROR; df->parse(r->idStr,result,ps); if ( U_SUCCESS(ps) ) { r->code = result.getLong(); // Convert string to number uhash_iput(numericCodeMap,r->code,(void *)r,&status); r->type = URGN_SUBCONTINENT; } else { r->code = Region::UNDEFINED_NUMERIC_CODE; } } // Process the territory aliases while ( ures_hasNext(territoryAlias) ) { UResourceBundle *res = ures_getNextResource(territoryAlias,NULL,&status); const char *aliasFrom = ures_getKey(res); UnicodeString* aliasFromStr = new UnicodeString(aliasFrom); UnicodeString aliasTo = ures_getUnicodeString(res,&status); ures_close(res); Region *aliasToRegion = (Region *) uhash_get(regionIDMap,&aliasTo); Region *aliasFromRegion = (Region *)uhash_get(regionIDMap,aliasFromStr); if ( aliasToRegion != NULL && aliasFromRegion == NULL ) { // This is just an alias from some string to a region uhash_put(regionAliases,(void *)aliasFromStr, (void *)aliasToRegion,&status); } else { if ( aliasFromRegion == NULL ) { // Deprecated region code not in the master codes list - so need to create a deprecated region for it. aliasFromRegion = new Region(); aliasFromRegion->idStr.setTo(*aliasFromStr); aliasFromRegion->idStr.extract(0,aliasFromRegion->idStr.length(),aliasFromRegion->id,sizeof(aliasFromRegion->id),US_INV); uhash_put(regionIDMap,(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status); Formattable result; UErrorCode ps = U_ZERO_ERROR; df->parse(aliasFromRegion->idStr,result,ps); if ( U_SUCCESS(ps) ) { aliasFromRegion->code = result.getLong(); // Convert string to number uhash_iput(numericCodeMap,aliasFromRegion->code,(void *)aliasFromRegion,&status); } else { aliasFromRegion->code = Region::UNDEFINED_NUMERIC_CODE; } aliasFromRegion->type = URGN_DEPRECATED; } else { aliasFromRegion->type = URGN_DEPRECATED; } delete aliasFromStr; aliasFromRegion->preferredValues = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); UnicodeString currentRegion; currentRegion.remove(); for (int32_t i = 0 ; i < aliasTo.length() ; i++ ) { if ( aliasTo.charAt(i) != 0x0020 ) { currentRegion.append(aliasTo.charAt(i)); } if ( aliasTo.charAt(i) == 0x0020 || i+1 == aliasTo.length() ) { Region *target = (Region *)uhash_get(regionIDMap,(void *)¤tRegion); if (target) { UnicodeString *preferredValue = new UnicodeString(target->idStr); aliasFromRegion->preferredValues->addElement((void *)preferredValue,status); } currentRegion.remove(); } } } } // Process the code mappings - This will allow us to assign numeric codes to most of the territories. while ( ures_hasNext(codeMappings) ) { UResourceBundle *mapping = ures_getNextResource(codeMappings,NULL,&status); if ( ures_getType(mapping) == URES_ARRAY && ures_getSize(mapping) == 3) { UnicodeString codeMappingID = ures_getUnicodeStringByIndex(mapping,0,&status); UnicodeString codeMappingNumber = ures_getUnicodeStringByIndex(mapping,1,&status); UnicodeString codeMapping3Letter = ures_getUnicodeStringByIndex(mapping,2,&status); Region *r = (Region *)uhash_get(regionIDMap,(void *)&codeMappingID); if ( r ) { Formattable result; UErrorCode ps = U_ZERO_ERROR; df->parse(codeMappingNumber,result,ps); if ( U_SUCCESS(ps) ) { r->code = result.getLong(); // Convert string to number uhash_iput(numericCodeMap,r->code,(void *)r,&status); } UnicodeString *code3 = new UnicodeString(codeMapping3Letter); uhash_put(regionAliases,(void *)code3, (void *)r,&status); } } ures_close(mapping); } // Now fill in the special cases for WORLD, UNKNOWN, CONTINENTS, and GROUPINGS Region *r; r = (Region *) uhash_get(regionIDMap,(void *)&WORLD_ID); if ( r ) { r->type = URGN_WORLD; } r = (Region *) uhash_get(regionIDMap,(void *)&UNKNOWN_REGION_ID); if ( r ) { r->type = URGN_UNKNOWN; } for ( int32_t i = 0 ; i < continents->size() ; i++ ) { r = (Region *) uhash_get(regionIDMap,(void *)continents->elementAt(i)); if ( r ) { r->type = URGN_CONTINENT; } } delete continents; for ( int32_t i = 0 ; i < groupings->size() ; i++ ) { r = (Region *) uhash_get(regionIDMap,(void *)groupings->elementAt(i)); if ( r ) { r->type = URGN_GROUPING; } } delete groupings; // Special case: The region code "QO" (Outlying Oceania) is a subcontinent code added by CLDR // even though it looks like a territory code. Need to handle it here. r = (Region *) uhash_get(regionIDMap,(void *)&OUTLYING_OCEANIA_REGION_ID); if ( r ) { r->type = URGN_SUBCONTINENT; } // Load territory containment info from the supplemental data. while ( ures_hasNext(territoryContainment) ) { UResourceBundle *mapping = ures_getNextResource(territoryContainment,NULL,&status); const char *parent = ures_getKey(mapping); UnicodeString parentStr = UnicodeString(parent); Region *parentRegion = (Region *) uhash_get(regionIDMap,(void *)&parentStr); for ( int j = 0 ; j < ures_getSize(mapping); j++ ) { UnicodeString child = ures_getUnicodeStringByIndex(mapping,j,&status); Region *childRegion = (Region *) uhash_get(regionIDMap,(void *)&child); if ( parentRegion != NULL && childRegion != NULL ) { // Add the child region to the set of regions contained by the parent if (parentRegion->containedRegions == NULL) { parentRegion->containedRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); } UnicodeString *childStr = new UnicodeString(status); childStr->fastCopyFrom(childRegion->idStr); parentRegion->containedRegions->addElement((void *)childStr,status); // Set the parent region to be the containing region of the child. // Regions of type GROUPING can't be set as the parent, since another region // such as a SUBCONTINENT, CONTINENT, or WORLD must always be the parent. if ( parentRegion->type != URGN_GROUPING) { childRegion->containingRegion = parentRegion; } } } ures_close(mapping); } // Create the availableRegions lists int32_t pos = -1; while ( const UHashElement* element = uhash_nextElement(regionIDMap,&pos)) { Region *ar = (Region *)element->value.pointer; if ( availableRegions[ar->type] == NULL ) { availableRegions[ar->type] = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); } UnicodeString *arString = new UnicodeString(ar->idStr); availableRegions[ar->type]->addElement((void *)arString,status); } ures_close(territoryContainment); ures_close(worldContainment); ures_close(groupingContainment); ures_close(codeMappings); ures_close(rb2); ures_close(territoryAlias); ures_close(regionCodes); ures_close(rb); delete df; ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); regionDataIsLoaded = true; umtx_unlock(&gRegionDataLock); }
/* * Initializes the region data from the ICU resource bundles. The region data * contains the basic relationships such as which regions are known, what the numeric * codes are, any known aliases, and the territory containment data. * * If the region data has already loaded, then this method simply returns without doing * anything meaningful. */ void Region::loadRegionData(UErrorCode &status) { // Construct service objs first LocalUHashtablePointer newRegionIDMap(uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status)); LocalUHashtablePointer newNumericCodeMap(uhash_open(uhash_hashLong,uhash_compareLong,NULL,&status)); LocalUHashtablePointer newRegionAliases(uhash_open(uhash_hashUnicodeString,uhash_compareUnicodeString,NULL,&status)); LocalPointer<DecimalFormat> df(new DecimalFormat(status), status); LocalPointer<UVector> continents(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); LocalPointer<UVector> groupings(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); allRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); LocalUResourceBundlePointer metadata(ures_openDirect(NULL,"metadata",&status)); LocalUResourceBundlePointer metadataAlias(ures_getByKey(metadata.getAlias(),"alias",NULL,&status)); LocalUResourceBundlePointer territoryAlias(ures_getByKey(metadataAlias.getAlias(),"territory",NULL,&status)); LocalUResourceBundlePointer supplementalData(ures_openDirect(NULL,"supplementalData",&status)); LocalUResourceBundlePointer codeMappings(ures_getByKey(supplementalData.getAlias(),"codeMappings",NULL,&status)); LocalUResourceBundlePointer idValidity(ures_getByKey(supplementalData.getAlias(),"idValidity",NULL,&status)); LocalUResourceBundlePointer regionList(ures_getByKey(idValidity.getAlias(),"region",NULL,&status)); LocalUResourceBundlePointer regionRegular(ures_getByKey(regionList.getAlias(),"regular",NULL,&status)); LocalUResourceBundlePointer regionMacro(ures_getByKey(regionList.getAlias(),"macroregion",NULL,&status)); LocalUResourceBundlePointer regionUnknown(ures_getByKey(regionList.getAlias(),"unknown",NULL,&status)); LocalUResourceBundlePointer territoryContainment(ures_getByKey(supplementalData.getAlias(),"territoryContainment",NULL,&status)); LocalUResourceBundlePointer worldContainment(ures_getByKey(territoryContainment.getAlias(),"001",NULL,&status)); LocalUResourceBundlePointer groupingContainment(ures_getByKey(territoryContainment.getAlias(),"grouping",NULL,&status)); if (U_FAILURE(status)) { return; } // now, initialize df->setParseIntegerOnly(TRUE); uhash_setValueDeleter(newRegionIDMap.getAlias(), deleteRegion); // regionIDMap owns objs uhash_setKeyDeleter(newRegionAliases.getAlias(), uprv_deleteUObject); // regionAliases owns the string keys while ( ures_hasNext(regionRegular.getAlias()) ) { UnicodeString regionName = ures_getNextUnicodeString(regionRegular.getAlias(),NULL,&status); int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); UChar buf[6]; regionName.extract(buf,6,status); if ( rangeMarkerLocation > 0 ) { UChar endRange = regionName.charAt(rangeMarkerLocation+1); buf[rangeMarkerLocation] = 0; while ( buf[rangeMarkerLocation-1] <= endRange ) { LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status); allRegions->addElement(newRegion.orphan(),status); buf[rangeMarkerLocation-1]++; } } else { LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status); allRegions->addElement(newRegion.orphan(),status); } } while ( ures_hasNext(regionMacro.getAlias()) ) { UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),NULL,&status); int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); UChar buf[6]; regionName.extract(buf,6,status); if ( rangeMarkerLocation > 0 ) { UChar endRange = regionName.charAt(rangeMarkerLocation+1); buf[rangeMarkerLocation] = 0; while ( buf[rangeMarkerLocation-1] <= endRange ) { LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status); allRegions->addElement(newRegion.orphan(),status); buf[rangeMarkerLocation-1]++; } } else { LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status); allRegions->addElement(newRegion.orphan(),status); } } while ( ures_hasNext(regionUnknown.getAlias()) ) { LocalPointer<UnicodeString> regionName (new UnicodeString(ures_getNextUnicodeString(regionUnknown.getAlias(),NULL,&status),status)); allRegions->addElement(regionName.orphan(),status); } while ( ures_hasNext(worldContainment.getAlias()) ) { UnicodeString *continentName = new UnicodeString(ures_getNextUnicodeString(worldContainment.getAlias(),NULL,&status)); continents->addElement(continentName,status); } while ( ures_hasNext(groupingContainment.getAlias()) ) { UnicodeString *groupingName = new UnicodeString(ures_getNextUnicodeString(groupingContainment.getAlias(),NULL,&status)); groupings->addElement(groupingName,status); } for ( int32_t i = 0 ; i < allRegions->size() ; i++ ) { LocalPointer<Region> r(new Region(), status); if ( U_FAILURE(status) ) { return; } UnicodeString *regionName = (UnicodeString *)allRegions->elementAt(i); r->idStr = *regionName; r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV); r->type = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known. Formattable result; UErrorCode ps = U_ZERO_ERROR; df->parse(r->idStr,result,ps); if ( U_SUCCESS(ps) ) { r->code = result.getLong(); // Convert string to number uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)(r.getAlias()),&status); r->type = URGN_SUBCONTINENT; } else { r->code = -1; } void* idStrAlias = (void*)&(r->idStr); // about to orphan 'r'. Save this off. uhash_put(newRegionIDMap.getAlias(),idStrAlias,(void *)(r.orphan()),&status); // regionIDMap takes ownership } // Process the territory aliases while ( ures_hasNext(territoryAlias.getAlias()) ) { LocalUResourceBundlePointer res(ures_getNextResource(territoryAlias.getAlias(),NULL,&status)); const char *aliasFrom = ures_getKey(res.getAlias()); LocalPointer<UnicodeString> aliasFromStr(new UnicodeString(aliasFrom, -1, US_INV), status); UnicodeString aliasTo = ures_getUnicodeStringByKey(res.getAlias(),"replacement",&status); res.adoptInstead(NULL); const Region *aliasToRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),&aliasTo); Region *aliasFromRegion = (Region *)uhash_get(newRegionIDMap.getAlias(),aliasFromStr.getAlias()); if ( aliasToRegion != NULL && aliasFromRegion == NULL ) { // This is just an alias from some string to a region uhash_put(newRegionAliases.getAlias(),(void *)aliasFromStr.orphan(), (void *)aliasToRegion,&status); } else { if ( aliasFromRegion == NULL ) { // Deprecated region code not in the master codes list - so need to create a deprecated region for it. LocalPointer<Region> newRgn(new Region, status); if ( U_SUCCESS(status) ) { aliasFromRegion = newRgn.orphan(); } else { return; // error out } aliasFromRegion->idStr.setTo(*aliasFromStr); aliasFromRegion->idStr.extract(0,aliasFromRegion->idStr.length(),aliasFromRegion->id,sizeof(aliasFromRegion->id),US_INV); uhash_put(newRegionIDMap.getAlias(),(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status); Formattable result; UErrorCode ps = U_ZERO_ERROR; df->parse(aliasFromRegion->idStr,result,ps); if ( U_SUCCESS(ps) ) { aliasFromRegion->code = result.getLong(); // Convert string to number uhash_iput(newNumericCodeMap.getAlias(),aliasFromRegion->code,(void *)aliasFromRegion,&status); } else { aliasFromRegion->code = -1; } aliasFromRegion->type = URGN_DEPRECATED; } else { aliasFromRegion->type = URGN_DEPRECATED; } { LocalPointer<UVector> newPreferredValues(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); aliasFromRegion->preferredValues = newPreferredValues.orphan(); } if( U_FAILURE(status)) { return; } UnicodeString currentRegion; //currentRegion.remove(); TODO: was already 0 length? for (int32_t i = 0 ; i < aliasTo.length() ; i++ ) { if ( aliasTo.charAt(i) != 0x0020 ) { currentRegion.append(aliasTo.charAt(i)); } if ( aliasTo.charAt(i) == 0x0020 || i+1 == aliasTo.length() ) { Region *target = (Region *)uhash_get(newRegionIDMap.getAlias(),(void *)¤tRegion); if (target) { LocalPointer<UnicodeString> preferredValue(new UnicodeString(target->idStr), status); aliasFromRegion->preferredValues->addElement((void *)preferredValue.orphan(),status); // may add null if err } currentRegion.remove(); } } } } // Process the code mappings - This will allow us to assign numeric codes to most of the territories. while ( ures_hasNext(codeMappings.getAlias()) ) { UResourceBundle *mapping = ures_getNextResource(codeMappings.getAlias(),NULL,&status); if ( ures_getType(mapping) == URES_ARRAY && ures_getSize(mapping) == 3) { UnicodeString codeMappingID = ures_getUnicodeStringByIndex(mapping,0,&status); UnicodeString codeMappingNumber = ures_getUnicodeStringByIndex(mapping,1,&status); UnicodeString codeMapping3Letter = ures_getUnicodeStringByIndex(mapping,2,&status); Region *r = (Region *)uhash_get(newRegionIDMap.getAlias(),(void *)&codeMappingID); if ( r ) { Formattable result; UErrorCode ps = U_ZERO_ERROR; df->parse(codeMappingNumber,result,ps); if ( U_SUCCESS(ps) ) { r->code = result.getLong(); // Convert string to number uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)r,&status); } LocalPointer<UnicodeString> code3(new UnicodeString(codeMapping3Letter), status); uhash_put(newRegionAliases.getAlias(),(void *)code3.orphan(), (void *)r,&status); } } ures_close(mapping); } // Now fill in the special cases for WORLD, UNKNOWN, CONTINENTS, and GROUPINGS Region *r; UnicodeString WORLD_ID_STRING(WORLD_ID); r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&WORLD_ID_STRING); if ( r ) { r->type = URGN_WORLD; } UnicodeString UNKNOWN_REGION_ID_STRING(UNKNOWN_REGION_ID); r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&UNKNOWN_REGION_ID_STRING); if ( r ) { r->type = URGN_UNKNOWN; } for ( int32_t i = 0 ; i < continents->size() ; i++ ) { r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)continents->elementAt(i)); if ( r ) { r->type = URGN_CONTINENT; } } for ( int32_t i = 0 ; i < groupings->size() ; i++ ) { r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)groupings->elementAt(i)); if ( r ) { r->type = URGN_GROUPING; } } // Special case: The region code "QO" (Outlying Oceania) is a subcontinent code added by CLDR // even though it looks like a territory code. Need to handle it here. UnicodeString OUTLYING_OCEANIA_REGION_ID_STRING(OUTLYING_OCEANIA_REGION_ID); r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&OUTLYING_OCEANIA_REGION_ID_STRING); if ( r ) { r->type = URGN_SUBCONTINENT; } // Load territory containment info from the supplemental data. while ( ures_hasNext(territoryContainment.getAlias()) ) { LocalUResourceBundlePointer mapping(ures_getNextResource(territoryContainment.getAlias(),NULL,&status)); if( U_FAILURE(status) ) { return; // error out } const char *parent = ures_getKey(mapping.getAlias()); if (uprv_strcmp(parent, "containedGroupings") == 0 || uprv_strcmp(parent, "deprecated") == 0) { continue; // handle new pseudo-parent types added in ICU data per cldrbug 7808; for now just skip. // #11232 is to do something useful with these. } UnicodeString parentStr = UnicodeString(parent, -1 , US_INV); Region *parentRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&parentStr); for ( int j = 0 ; j < ures_getSize(mapping.getAlias()); j++ ) { UnicodeString child = ures_getUnicodeStringByIndex(mapping.getAlias(),j,&status); Region *childRegion = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&child); if ( parentRegion != NULL && childRegion != NULL ) { // Add the child region to the set of regions contained by the parent if (parentRegion->containedRegions == NULL) { parentRegion->containedRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); } LocalPointer<UnicodeString> childStr(new UnicodeString(), status); if( U_FAILURE(status) ) { return; // error out } childStr->fastCopyFrom(childRegion->idStr); parentRegion->containedRegions->addElement((void *)childStr.orphan(),status); // Set the parent region to be the containing region of the child. // Regions of type GROUPING can't be set as the parent, since another region // such as a SUBCONTINENT, CONTINENT, or WORLD must always be the parent. if ( parentRegion->type != URGN_GROUPING) { childRegion->containingRegion = parentRegion; } } } } // Create the availableRegions lists int32_t pos = UHASH_FIRST; while ( const UHashElement* element = uhash_nextElement(newRegionIDMap.getAlias(),&pos)) { Region *ar = (Region *)element->value.pointer; if ( availableRegions[ar->type] == NULL ) { LocalPointer<UVector> newAr(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); availableRegions[ar->type] = newAr.orphan(); } LocalPointer<UnicodeString> arString(new UnicodeString(ar->idStr), status); if( U_FAILURE(status) ) { return; // error out } availableRegions[ar->type]->addElement((void *)arString.orphan(),status); } ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); // copy hashtables numericCodeMap = newNumericCodeMap.orphan(); regionIDMap = newRegionIDMap.orphan(); regionAliases = newRegionAliases.orphan(); }
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; }