Пример #1
0
static Array HHVM_STATIC_METHOD(Locale, getKeywords, const String& locale) {
  UErrorCode error = U_ZERO_ERROR;
  String locname = localeOrDefault(locale);
  UEnumeration *e = uloc_openKeywords(locname.c_str(), &error);
  if (!e) return null_array;

  Array ret = Array::Create();
  const char *key;
  int key_len;
  String val(128, ReserveString);
  char *ptr = val->mutableData();
  error = U_ZERO_ERROR;
  while ((key = uenum_next(e, &key_len, &error))) {
tryagain:
    error = U_ZERO_ERROR;
    int val_len = uloc_getKeywordValue(locname.c_str(), key,
                                       ptr, val->capacity(), &error);
    if (error == U_BUFFER_OVERFLOW_ERROR) {
      val = String(val_len + 128, ReserveString);
      ptr = val->mutableData();
      goto tryagain;
    }
    if (U_FAILURE(error)) {
      s_intl_error->setError(error, "locale_get_keywords: Error encountered "
                                    "while getting the keyword  value for the "
                                    " keyword");
      return null_array;
    }
    ret.set(String(key, key_len, CopyString), String(ptr, val_len, CopyString));
  }
  return ret;
}
Пример #2
0
int32_t GlobalizationNative_GetDefaultLocaleName(UChar* value, int32_t valueLength)
{
    char localeNameBuffer[ULOC_FULLNAME_CAPACITY];
    UErrorCode status = U_ZERO_ERROR;

    const char* defaultLocale = DetectDefaultLocaleName();

    uloc_getBaseName(defaultLocale, localeNameBuffer, ULOC_FULLNAME_CAPACITY, &status);
    u_charsToUChars_safe(localeNameBuffer, value, valueLength, &status);

    if (U_SUCCESS(status))
    {
        int localeNameLen = FixupLocaleName(value, valueLength);

        char collationValueTemp[ULOC_KEYWORDS_CAPACITY];
        int32_t collationLen =
            uloc_getKeywordValue(defaultLocale, "collation", collationValueTemp, ULOC_KEYWORDS_CAPACITY, &status);

        if (U_SUCCESS(status) && collationLen > 0)
        {
            // copy the collation; managed uses a "_" to represent collation (not
            // "@collation=")
            u_charsToUChars_safe("_", &value[localeNameLen], valueLength - localeNameLen, &status);
            u_charsToUChars_safe(collationValueTemp, &value[localeNameLen + 1], valueLength - localeNameLen - 1, &status);
        }
    }

    return UErrorCodeToBool(status);
}
Пример #3
0
U_CAPI void U_EXPORT2
ucol_prepareShortStringOpen( const char *definition,
                          UBool,
                          UParseError *parseError,
                          UErrorCode *status)
{
    if(U_FAILURE(*status)) return;

    UParseError internalParseError;

    if(!parseError) {
        parseError = &internalParseError;
    }
    parseError->line = 0;
    parseError->offset = 0;
    parseError->preContext[0] = 0;
    parseError->postContext[0] = 0;


    // first we want to pick stuff out of short string.
    // we'll end up with an UCA version, locale and a bunch of
    // settings

    // analyse the string in order to get everything we need.
    CollatorSpec s;
    ucol_sit_initCollatorSpecs(&s);
    ucol_sit_readSpecs(&s, definition, parseError, status);
    ucol_sit_calculateWholeLocale(&s);

    char buffer[internalBufferSize];
    uprv_memset(buffer, 0, internalBufferSize);
    uloc_canonicalize(s.locale, buffer, internalBufferSize, status);

    UResourceBundle *b = ures_open(U_ICUDATA_COLL, buffer, status);
    /* we try to find stuff from keyword */
    UResourceBundle *collations = ures_getByKey(b, "collations", NULL, status);
    UResourceBundle *collElem = NULL;
    char keyBuffer[256];
    // if there is a keyword, we pick it up and try to get elements
    if(!uloc_getKeywordValue(buffer, "collation", keyBuffer, 256, status)) {
      // no keyword. we try to find the default setting, which will give us the keyword value
      UResourceBundle *defaultColl = ures_getByKeyWithFallback(collations, "default", NULL, status);
      if(U_SUCCESS(*status)) {
        int32_t defaultKeyLen = 0;
        const UChar *defaultKey = ures_getString(defaultColl, &defaultKeyLen, status);
        u_UCharsToChars(defaultKey, keyBuffer, defaultKeyLen);
        keyBuffer[defaultKeyLen] = 0;
      } else {
        *status = U_INTERNAL_PROGRAM_ERROR;
        return;
      }
      ures_close(defaultColl);
    }
    collElem = ures_getByKeyWithFallback(collations, keyBuffer, collElem, status);
    ures_close(collElem);
    ures_close(collations);
    ures_close(b);
}
Пример #4
0
U_NAMESPACE_END

// The following must at least allow for rg key value (6) plus terminator (1).
#define ULOC_RG_BUFLEN 8

U_CAPI int32_t U_EXPORT2
ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion,
                                     char *region, int32_t regionCapacity, UErrorCode* status) {
    if (U_FAILURE(*status)) {
        return 0;
    }
    char rgBuf[ULOC_RG_BUFLEN];
    UErrorCode rgStatus = U_ZERO_ERROR;

    // First check for rg keyword value
    int32_t rgLen = uloc_getKeywordValue(localeID, "rg", rgBuf, ULOC_RG_BUFLEN, &rgStatus);
    if (U_FAILURE(rgStatus) || rgLen != 6) {
        rgLen = 0;
    } else {
        // rgBuf guaranteed to be zero terminated here, with text len 6
        char *rgPtr = rgBuf;
        for (; *rgPtr!= 0; rgPtr++) {
            *rgPtr = uprv_toupper(*rgPtr);
        }
        rgLen = (uprv_strcmp(rgBuf+2, "ZZZZ") == 0)? 2: 0;
    }

    if (rgLen == 0) {
        // No valid rg keyword value, try for unicode_region_subtag
        rgLen = uloc_getCountry(localeID, rgBuf, ULOC_RG_BUFLEN, status);
        if (U_FAILURE(*status)) {
            rgLen = 0;
        } else if (rgLen == 0 && inferRegion) {
            // no unicode_region_subtag but inferRegion TRUE, try likely subtags
            char locBuf[ULOC_FULLNAME_CAPACITY];
            rgStatus = U_ZERO_ERROR;
            (void)uloc_addLikelySubtags(localeID, locBuf, ULOC_FULLNAME_CAPACITY, &rgStatus);
            if (U_SUCCESS(rgStatus)) {
                rgLen = uloc_getCountry(locBuf, rgBuf, ULOC_RG_BUFLEN, status);
                if (U_FAILURE(*status)) {
                    rgLen = 0;
                }
            }
        }
    }

    rgBuf[rgLen] = 0;
    uprv_strncpy(region, rgBuf, regionCapacity);
    return u_terminateChars(region, regionCapacity, rgLen, status);
}
Пример #5
0
static bool __CFLocaleCopyICUKeyword(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context, const char *keyword)
{
    char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
    if (CFStringGetCString(locale->_identifier, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII))
    {
        char value[ULOC_KEYWORD_AND_VALUES_CAPACITY];
        UErrorCode icuStatus = U_ZERO_ERROR;
        if (uloc_getKeywordValue(localeID, keyword, value, sizeof(value)/sizeof(char), &icuStatus) > 0 && U_SUCCESS(icuStatus))
        {
            *cf = (CFTypeRef) CFStringCreateWithCString(kCFAllocatorSystemDefault, value, kCFStringEncodingASCII);
            return true;
        }
    }
    *cf = NULL;
    return false;
}
Пример #6
0
U_CAPI int32_t U_EXPORT2
uloc_getDisplayKeywordValue(   const char* locale,
                               const char* keyword,
                               const char* displayLocale,
                               UChar* dest,
                               int32_t destCapacity,
                               UErrorCode* status){


    char keywordValue[ULOC_FULLNAME_CAPACITY*4];
    int32_t capacity = ULOC_FULLNAME_CAPACITY*4;
    int32_t keywordValueLen =0;

    /* argument checking */
    if(status==NULL || U_FAILURE(*status)) {
        return 0;
    }

    if(destCapacity<0 || (destCapacity>0 && dest==NULL)) {
        *status=U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    /* get the keyword value */
    keywordValue[0]=0;
    keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, capacity, status);

    /* 
     * if the keyword is equal to currency .. then to get the display name 
     * we need to do the fallback ourselves
     */
    if(uprv_stricmp(keyword, _kCurrency)==0){

        int32_t dispNameLen = 0;
        const UChar *dispName = NULL;
        
        UResourceBundle *bundle     = ures_open(U_ICUDATA_CURR, displayLocale, status);
        UResourceBundle *currencies = ures_getByKey(bundle, _kCurrencies, NULL, status);
        UResourceBundle *currency   = ures_getByKeyWithFallback(currencies, keywordValue, NULL, status);
        
        dispName = ures_getStringByIndex(currency, UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status);
        
        /*close the bundles */
        ures_close(currency);
        ures_close(currencies);
        ures_close(bundle);
        
        if(U_FAILURE(*status)){
            if(*status == U_MISSING_RESOURCE_ERROR){
                /* we just want to write the value over if nothing is available */
                *status = U_USING_DEFAULT_WARNING;
            }else{
                return 0;
            }
        }

        /* now copy the dispName over if not NULL */
        if(dispName != NULL){
            if(dispNameLen <= destCapacity){
                uprv_memcpy(dest, dispName, dispNameLen * U_SIZEOF_UCHAR);
                return u_terminateUChars(dest, destCapacity, dispNameLen, status);
            }else{
                *status = U_BUFFER_OVERFLOW_ERROR;
                return dispNameLen;
            }
        }else{
            /* we have not found the display name for the value .. just copy over */
            if(keywordValueLen <= destCapacity){
                u_charsToUChars(keywordValue, dest, keywordValueLen);
                return u_terminateUChars(dest, destCapacity, keywordValueLen, status);
            }else{
                 *status = U_BUFFER_OVERFLOW_ERROR;
                return keywordValueLen;
            }
        }

        
    }else{

        return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale,
                                   _kTypes, keyword, 
                                   keywordValue,
                                   keywordValue,
                                   dest, destCapacity,
                                   status);
    }
}
U_CFUNC UCollator*
ucol_open_internal(const char *loc,
                   UErrorCode *status)
{
    const UCollator* UCA = ucol_initUCA(status);

    /* New version */
    if(U_FAILURE(*status)) return 0;



    UCollator *result = NULL;
    UResourceBundle *b = ures_open(U_ICUDATA_COLL, loc, status);

    /* we try to find stuff from keyword */
    UResourceBundle *collations = ures_getByKey(b, "collations", NULL, status);
    UResourceBundle *collElem = NULL;
    char keyBuffer[256];
    // if there is a keyword, we pick it up and try to get elements
    if(!uloc_getKeywordValue(loc, "collation", keyBuffer, 256, status)) {
        // no keyword. we try to find the default setting, which will give us the keyword value
        UErrorCode intStatus = U_ZERO_ERROR;
        // finding default value does not affect collation fallback status
        UResourceBundle *defaultColl = ures_getByKeyWithFallback(collations, "default", NULL, &intStatus);
        if(U_SUCCESS(intStatus)) {
            int32_t defaultKeyLen = 0;
            const UChar *defaultKey = ures_getString(defaultColl, &defaultKeyLen, &intStatus);
            u_UCharsToChars(defaultKey, keyBuffer, defaultKeyLen);
            keyBuffer[defaultKeyLen] = 0;
        } else {
            *status = U_INTERNAL_PROGRAM_ERROR;
            return NULL;
        }
        ures_close(defaultColl);
    }
    collElem = ures_getByKeyWithFallback(collations, keyBuffer, collElem, status);

    UResourceBundle *binary = NULL;

    if(*status == U_MISSING_RESOURCE_ERROR) { /* We didn't find the tailoring data, we fallback to the UCA */
        *status = U_USING_DEFAULT_WARNING;
        result = ucol_initCollator(UCA->image, result, UCA, status);
        // if we use UCA, real locale is root
        result->rb = ures_open(U_ICUDATA_COLL, "", status);
        result->elements = ures_open(U_ICUDATA_COLL, "", status);
        if(U_FAILURE(*status)) {
            goto clean;
        }
        ures_close(b);
        result->hasRealData = FALSE;
    } else if(U_SUCCESS(*status)) {
        int32_t len = 0;
        UErrorCode binaryStatus = U_ZERO_ERROR;

        binary = ures_getByKey(collElem, "%%CollationBin", NULL, &binaryStatus);

        if(binaryStatus == U_MISSING_RESOURCE_ERROR) { /* we didn't find the binary image, we should use the rules */
            binary = NULL;
            result = tryOpeningFromRules(collElem, status);
            if(U_FAILURE(*status)) {
                goto clean;
            }
        } else if(U_SUCCESS(*status)) { /* otherwise, we'll pick a collation data that exists */
            const uint8_t *inData = ures_getBinary(binary, &len, status);
            UCATableHeader *colData = (UCATableHeader *)inData;
            if(uprv_memcmp(colData->UCAVersion, UCA->image->UCAVersion, sizeof(UVersionInfo)) != 0 ||
                uprv_memcmp(colData->UCDVersion, UCA->image->UCDVersion, sizeof(UVersionInfo)) != 0 ||
                colData->version[0] != UCOL_BUILDER_VERSION)
            {
                *status = U_DIFFERENT_UCA_VERSION;
                result = tryOpeningFromRules(collElem, status);
            } else {
                if(U_FAILURE(*status)){
                    goto clean;
                }
                if((uint32_t)len > (paddedsize(sizeof(UCATableHeader)) + paddedsize(sizeof(UColOptionSet)))) {
                    result = ucol_initCollator((const UCATableHeader *)inData, result, UCA, status);
                    if(U_FAILURE(*status)){
                        goto clean;
                    }
                    result->hasRealData = TRUE;
                } else {
                    result = ucol_initCollator(UCA->image, result, UCA, status);
                    ucol_setOptionsFromHeader(result, (UColOptionSet *)(inData+((const UCATableHeader *)inData)->options), status);
                    if(U_FAILURE(*status)){
                        goto clean;
                    }
                    result->hasRealData = FALSE;
                }
                result->freeImageOnClose = FALSE;
            }
        }
        result->rb = b;
        result->elements = collElem;
        len = 0;
        binaryStatus = U_ZERO_ERROR;
        result->rules = ures_getStringByKey(result->elements, "Sequence", &len, &binaryStatus);
        result->rulesLength = len;
        result->freeRulesOnClose = FALSE;
    } else { /* There is another error, and we're just gonna clean up */
        goto clean;
    }

    result->validLocale = NULL; // default is to use rb info

    if(loc == NULL) {
        loc = ures_getLocale(result->rb, status);
    }
    result->requestedLocale = (char *)uprv_malloc((uprv_strlen(loc)+1)*sizeof(char));
    /* test for NULL */
    if (result->requestedLocale == NULL) {
        *status = U_MEMORY_ALLOCATION_ERROR;
        goto clean;
    }
    uprv_strcpy(result->requestedLocale, loc);

    ures_close(binary);
    ures_close(collations); //??? we have to decide on that. Probably affects something :)
    result->resCleaner = ucol_prv_closeResources;
    return result;

clean:
    ures_close(b);
    ures_close(collElem);
    ures_close(collations);
    ures_close(binary);
    return NULL;
}
U_CAPI int32_t U_EXPORT2
ucurr_forLocale(const char* locale,
                UChar* buff,
                int32_t buffCapacity,
                UErrorCode* ec)
{
    int32_t resLen = 0;
    const UChar* s = NULL;
    if (ec != NULL && U_SUCCESS(*ec)) {
        if ((buff && buffCapacity) || !buffCapacity) {
            UErrorCode localStatus = U_ZERO_ERROR;
            char id[ULOC_FULLNAME_CAPACITY];
            if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) {
                // there is a currency keyword. Try to see if it's valid
                if(buffCapacity > resLen) {
                    u_charsToUChars(id, buff, resLen);
                }
            } else {
                // get country or country_variant in `id'
                uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);

                if (U_FAILURE(*ec)) {
                    return 0;
                }

#if !UCONFIG_NO_SERVICE
                const UChar* result = CReg::get(id);
                if (result) {
                    if(buffCapacity > u_strlen(result)) {
                        u_strcpy(buff, result);
                    }
                    return u_strlen(result);
                }
#endif
                // Remove variants, which is only needed for registration.
                char *idDelim = strchr(id, VAR_DELIM);
                if (idDelim) {
                    idDelim[0] = 0;
                }

                // Look up the CurrencyMap element in the root bundle.
                UResourceBundle *rb = ures_openDirect(NULL, CURRENCY_DATA, &localStatus);
                UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
                UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
                UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
                s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);

                /*
                Get the second item when PREEURO is requested, and this is a known Euro country.
                If the requested variant is PREEURO, and this isn't a Euro country, assume
                that the country changed over to the Euro in the future. This is probably
                an old version of ICU that hasn't been updated yet. The latest currency is
                probably correct.
                */
                if (U_SUCCESS(localStatus)) {
                    if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
                        currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
                        s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
                    }
                    else if ((variantType & VARIANT_IS_EURO)) {
                        s = EUR_STR;
                    }
                }
                ures_close(countryArray);
                ures_close(currencyReq);

                if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0)
                {
                    // We don't know about it.  Check to see if we support the variant.
                    uloc_getParent(locale, id, sizeof(id), ec);
                    *ec = U_USING_FALLBACK_WARNING;
                    return ucurr_forLocale(id, buff, buffCapacity, ec);
                }
                else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
                    // There is nothing to fallback to. Report the failure/warning if possible.
                    *ec = localStatus;
                }
                if (U_SUCCESS(*ec)) {
                    if(buffCapacity > resLen) {
                        u_strcpy(buff, s);
                    }
                }
            }
            return u_terminateUChars(buff, buffCapacity, resLen, ec);
        } else {
            *ec = U_ILLEGAL_ARGUMENT_ERROR;
        }
    }
    return resLen;
}
Пример #9
0
U_CAPI int32_t U_EXPORT2
ucol_getShortDefinitionString(const UCollator *coll,
                              const char *locale,
                              char *dst,
                              int32_t capacity,
                              UErrorCode *status)
{
    if(U_FAILURE(*status)) return 0;
    if(coll->delegate != NULL) {
      return ((icu::Collator*)coll->delegate)->internalGetShortDefinitionString(locale,dst,capacity,*status);
    }
    char buffer[internalBufferSize];
    uprv_memset(buffer, 0, internalBufferSize*sizeof(char));
    int32_t resultSize = 0;
    char tempbuff[internalBufferSize];
    char locBuff[internalBufferSize];
    uprv_memset(buffer, 0, internalBufferSize*sizeof(char));
    int32_t elementSize = 0;
    UBool isAvailable = 0;
    CollatorSpec s;
    ucol_sit_initCollatorSpecs(&s);

    if(!locale) {
        locale = ucol_getLocaleByType(coll, ULOC_VALID_LOCALE, status);
    }
    elementSize = ucol_getFunctionalEquivalent(locBuff, internalBufferSize, "collation", locale, &isAvailable, status);

    if(elementSize) {
        // we should probably canonicalize here...
        elementSize = uloc_getLanguage(locBuff, tempbuff, internalBufferSize, status);
        appendShortStringElement(tempbuff, elementSize, buffer, &resultSize, /*capacity*/internalBufferSize, languageArg);
        elementSize = uloc_getCountry(locBuff, tempbuff, internalBufferSize, status);
        appendShortStringElement(tempbuff, elementSize, buffer, &resultSize, /*capacity*/internalBufferSize, regionArg);
        elementSize = uloc_getScript(locBuff, tempbuff, internalBufferSize, status);
        appendShortStringElement(tempbuff, elementSize, buffer, &resultSize, /*capacity*/internalBufferSize, scriptArg);
        elementSize = uloc_getVariant(locBuff, tempbuff, internalBufferSize, status);
        appendShortStringElement(tempbuff, elementSize, buffer, &resultSize, /*capacity*/internalBufferSize, variantArg);
        elementSize = uloc_getKeywordValue(locBuff, "collation", tempbuff, internalBufferSize, status);
        appendShortStringElement(tempbuff, elementSize, buffer, &resultSize, /*capacity*/internalBufferSize, keywordArg);
    }

    int32_t i = 0;
    UColAttributeValue attribute = UCOL_DEFAULT;
    for(i = 0; i < UCOL_SIT_ITEMS_COUNT; i++) {
        if(options[i].action == _processCollatorOption) {
            attribute = ucol_getAttributeOrDefault(coll, (UColAttribute)options[i].attr, status);
            if(attribute != UCOL_DEFAULT) {
                char letter = ucol_sit_attributeValueToLetter(attribute, status);
                appendShortStringElement(&letter, 1,
                    buffer, &resultSize, /*capacity*/internalBufferSize, options[i].optionStart);
            }
        }
    }
    if(coll->variableTopValueisDefault == FALSE) {
        //s.variableTopValue = ucol_getVariableTop(coll, status);
        elementSize = T_CString_integerToString(tempbuff, coll->variableTopValue, 16);
        appendShortStringElement(tempbuff, elementSize, buffer, &resultSize, capacity, variableTopValArg);
    }

    UParseError parseError;
    return ucol_normalizeShortDefinitionString(buffer, dst, capacity, &parseError, status);
}
Пример #10
0
U_CAPI int32_t U_EXPORT2
uloc_getDisplayName(const char * locale,
                    const char * displayLocale,
                    UChar * dest, int32_t destCapacity,
                    UErrorCode * pErrorCode)
{
	int32_t length, length2, length3 = 0;
	UBool hasLanguage, hasScript, hasCountry, hasVariant, hasKeywords;
	UEnumeration * keywordEnum = NULL;
	int32_t keywordCount = 0;
	const char * keyword = NULL;
	int32_t keywordLen = 0;
	char keywordValue[256];
	int32_t keywordValueLen = 0;

	int32_t locSepLen = 0;
	int32_t locPatLen = 0;
	int32_t p0Len = 0;
	int32_t defaultPatternLen = 9;
	const UChar * dispLocSeparator;
	const UChar * dispLocPattern;
	static const UChar defaultSeparator[3] = { 0x002c, 0x0020 , 0x0000 }; /* comma + space */
	static const UChar defaultPattern[10] = { 0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000 }; /* {0} ({1}) */
	static const UChar pat0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */
	static const UChar pat1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */

	UResourceBundle * bundle = NULL;
	UResourceBundle * locdsppat = NULL;

	UErrorCode status = U_ZERO_ERROR;

	/* argument checking */
	if (pErrorCode == NULL || U_FAILURE(*pErrorCode))
	{
		return 0;
	}

	if (destCapacity < 0 || (destCapacity > 0 && dest == NULL))
	{
		*pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
		return 0;
	}

	bundle    = ures_open(U_ICUDATA_LANG, displayLocale, &status);

	locdsppat = ures_getByKeyWithFallback(bundle, _kLocaleDisplayPattern, NULL, &status);
	dispLocSeparator = ures_getStringByKeyWithFallback(locdsppat, _kSeparator, &locSepLen, &status);
	dispLocPattern = ures_getStringByKeyWithFallback(locdsppat, _kPattern, &locPatLen, &status);

	/*close the bundles */
	ures_close(locdsppat);
	ures_close(bundle);

	/* If we couldn't find any data, then use the defaults */
	if (locSepLen == 0)
	{
		dispLocSeparator = defaultSeparator;
		locSepLen = 2;
	}

	if (locPatLen == 0)
	{
		dispLocPattern = defaultPattern;
		locPatLen = 9;
	}

	/*
	 * if there is a language, then write "language (country, variant)"
	 * otherwise write "country, variant"
	 */

	/* write the language */
	length = uloc_getDisplayLanguage(locale, displayLocale,
	                                 dest, destCapacity,
	                                 pErrorCode);
	hasLanguage = length > 0;

	if (hasLanguage)
	{
		p0Len = length;

		/* append " (" */
		if (length < destCapacity)
		{
			dest[length] = 0x20;
		}
		++length;
		if (length < destCapacity)
		{
			dest[length] = 0x28;
		}
		++length;
	}

	if (*pErrorCode == U_BUFFER_OVERFLOW_ERROR)
	{
		/* keep preflighting */
		*pErrorCode = U_ZERO_ERROR;
	}

	/* append the script */
	if (length < destCapacity)
	{
		length2 = uloc_getDisplayScript(locale, displayLocale,
		                                dest + length, destCapacity - length,
		                                pErrorCode);
	}
	else
	{
		length2 = uloc_getDisplayScript(locale, displayLocale,
		                                NULL, 0,
		                                pErrorCode);
	}
	hasScript = length2 > 0;
	length += length2;

	if (hasScript)
	{
		/* append separator */
		if (length + locSepLen <= destCapacity)
		{
			u_memcpy(dest + length, dispLocSeparator, locSepLen);
		}
		length += locSepLen;
	}

	if (*pErrorCode == U_BUFFER_OVERFLOW_ERROR)
	{
		/* keep preflighting */
		*pErrorCode = U_ZERO_ERROR;
	}

	/* append the country */
	if (length < destCapacity)
	{
		length2 = uloc_getDisplayCountry(locale, displayLocale,
		                                 dest + length, destCapacity - length,
		                                 pErrorCode);
	}
	else
	{
		length2 = uloc_getDisplayCountry(locale, displayLocale,
		                                 NULL, 0,
		                                 pErrorCode);
	}
	hasCountry = length2 > 0;
	length += length2;

	if (hasCountry)
	{
		/* append separator */
		if (length + locSepLen <= destCapacity)
		{
			u_memcpy(dest + length, dispLocSeparator, locSepLen);
		}
		length += locSepLen;
	}

	if (*pErrorCode == U_BUFFER_OVERFLOW_ERROR)
	{
		/* keep preflighting */
		*pErrorCode = U_ZERO_ERROR;
	}

	/* append the variant */
	if (length < destCapacity)
	{
		length2 = uloc_getDisplayVariant(locale, displayLocale,
		                                 dest + length, destCapacity - length,
		                                 pErrorCode);
	}
	else
	{
		length2 = uloc_getDisplayVariant(locale, displayLocale,
		                                 NULL, 0,
		                                 pErrorCode);
	}
	hasVariant = length2 > 0;
	length += length2;

	if (hasVariant)
	{
		/* append separator */
		if (length + locSepLen <= destCapacity)
		{
			u_memcpy(dest + length, dispLocSeparator, locSepLen);
		}
		length += locSepLen;
	}

	keywordEnum = uloc_openKeywords(locale, pErrorCode);

	for (keywordCount = uenum_count(keywordEnum, pErrorCode); keywordCount > 0 ; keywordCount--)
	{
		if (U_FAILURE(*pErrorCode))
		{
			break;
		}
		/* the uenum_next returns NUL terminated string */
		keyword = uenum_next(keywordEnum, &keywordLen, pErrorCode);
		if (length + length3 < destCapacity)
		{
			length3 += uloc_getDisplayKeyword(keyword, displayLocale, dest + length + length3, destCapacity - length - length3,
			                                  pErrorCode);
		}
		else
		{
			length3 += uloc_getDisplayKeyword(keyword, displayLocale, NULL, 0, pErrorCode);
		}
		if (*pErrorCode == U_BUFFER_OVERFLOW_ERROR)
		{
			/* keep preflighting */
			*pErrorCode = U_ZERO_ERROR;
		}
		keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, 256, pErrorCode);
		if (keywordValueLen)
		{
			if (length + length3 < destCapacity)
			{
				dest[length + length3] = 0x3D;
			}
			length3++;
			if (length + length3 < destCapacity)
			{
				length3 += uloc_getDisplayKeywordValue(locale, keyword, displayLocale, dest + length + length3,
				                                       destCapacity - length - length3, pErrorCode);
			}
			else
			{
				length3 += uloc_getDisplayKeywordValue(locale, keyword, displayLocale, NULL, 0, pErrorCode);
			}
			if (*pErrorCode == U_BUFFER_OVERFLOW_ERROR)
			{
				/* keep preflighting */
				*pErrorCode = U_ZERO_ERROR;
			}
		}
		if (keywordCount > 1)
		{
			if (length + length3 + locSepLen <= destCapacity && keywordCount)
			{
				u_memcpy(dest + length + length3, dispLocSeparator, locSepLen);
				length3 += locSepLen;
			}
		}
	}
	uenum_close(keywordEnum);

	hasKeywords = length3 > 0;
	length += length3;


	if ((hasScript && !hasCountry)
	    || ((hasScript || hasCountry) && !hasVariant && !hasKeywords)
	    || ((hasScript || hasCountry || hasVariant) && !hasKeywords))
	{
		/* Remove separator  */
		length -= locSepLen;
	}
	else if (hasLanguage && !hasScript && !hasCountry && !hasVariant && !hasKeywords)
	{
		/* Remove " (" */
		length -= 2;
	}

	if (hasLanguage && (hasScript || hasCountry || hasVariant || hasKeywords))
	{
		/* append ")" */
		if (length < destCapacity)
		{
			dest[length] = 0x29;
		}
		++length;

		/* If the localized display pattern is something other than the default pattern of "{0} ({1})", then
		 * then we need to do the formatting here.  It would be easier to use a messageFormat to do this, but we
		 * can't since we don't have the APIs in the i18n library available to us at this point.
		 */
		if (locPatLen != defaultPatternLen ||
		    u_strcmp(dispLocPattern, defaultPattern))  /* Something other than the default pattern */
		{
			UChar * p0 = u_strstr(dispLocPattern, pat0);
			UChar * p1 = u_strstr(dispLocPattern, pat1);
			u_terminateUChars(dest, destCapacity, length, pErrorCode);

			if (p0 != NULL && p1 != NULL)     /* The pattern is well formed */
			{
				if (dest)
				{
					int32_t destLen = 0;
					UChar * result = (UChar *)uprv_malloc((length + 1) * sizeof(UChar));
					UChar * upos = (UChar *)dispLocPattern;
					u_strcpy(result, dest);
					dest[0] = 0;
					while (*upos)
					{
						if (upos == p0)     /* Handle {0} substitution */
						{
							u_strncat(dest, result, p0Len);
							destLen += p0Len;
							dest[destLen] = 0; /* Null terminate */
							upos += 3;
						}
						else if (upos == p1)       /* Handle {1} substitution */
						{
							UChar * p1Start = &result[p0Len + 2];
							u_strncat(dest, p1Start, length - p0Len - 3);
							destLen += (length - p0Len - 3);
							dest[destLen] = 0; /* Null terminate */
							upos += 3;
						}
						else     /* Something from the pattern not {0} or {1} */
						{
							u_strncat(dest, upos, 1);
							upos++;
							destLen++;
							dest[destLen] = 0; /* Null terminate */
						}
					}
					length = destLen;
					uprv_free(result);
				}
			}
		}
	}
	if (*pErrorCode == U_BUFFER_OVERFLOW_ERROR)
	{
		/* keep preflighting */
		*pErrorCode = U_ZERO_ERROR;
	}

	return u_terminateUChars(dest, destCapacity, length, pErrorCode);
}