extern "C" jstring Java_libcore_icu_ICU_getScript(JNIEnv* env, jclass, jstring javaLocale) { UErrorCode status = U_ZERO_ERROR; ScopedUtfChars localeID(env, javaLocale); char script[ULOC_SCRIPT_CAPACITY]; uloc_getScript(localeID.c_str(), script, sizeof(script), &status); if (U_FAILURE(status)) { return NULL; } return env->NewStringUTF(script); }
// Implemented here because this calls uloc_addLikelySubtags(). U_CAPI UBool U_EXPORT2 uloc_isRightToLeft(const char *locale) { UErrorCode errorCode = U_ZERO_ERROR; char script[8]; int32_t scriptLength = uloc_getScript(locale, script, UPRV_LENGTHOF(script), &errorCode); if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING || scriptLength == 0) { // Fastpath: We know the likely scripts and their writing direction // for some common languages. errorCode = U_ZERO_ERROR; char lang[8]; int32_t langLength = uloc_getLanguage(locale, lang, UPRV_LENGTHOF(lang), &errorCode); if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING || langLength == 0) { return FALSE; } const char* langPtr = uprv_strstr(LANG_DIR_STRING, lang); if (langPtr != NULL) { switch (langPtr[langLength]) { case '-': return FALSE; case '+': return TRUE; default: break; // partial match of a longer code } } // Otherwise, find the likely script. errorCode = U_ZERO_ERROR; char likely[ULOC_FULLNAME_CAPACITY]; (void)uloc_addLikelySubtags(locale, likely, UPRV_LENGTHOF(likely), &errorCode); if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) { return FALSE; } scriptLength = uloc_getScript(likely, script, UPRV_LENGTHOF(script), &errorCode); if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING || scriptLength == 0) { return FALSE; } } UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script); return uscript_isRightToLeft(scriptCode); }
/* {{{ * Gets the value from ICU * common code shared by get_primary_language,get_script or get_region or get_variant * result = 0 if error, 1 if successful , -1 if no value */ static char* get_icu_value_internal( char* loc_name , char* tag_name, int* result , int fromParseLocale) { char* tag_value = NULL; int32_t tag_value_len = 512; int singletonPos = 0; char* mod_loc_name = NULL; int grOffset = 0; int32_t buflen = 512; UErrorCode status = U_ZERO_ERROR; if( tag_name != LOC_CANONICALIZE_TAG ){ /* Handle grandfathered languages */ grOffset = findOffset( LOC_GRANDFATHERED , loc_name ); if( grOffset >= 0 ){ if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ tag_value = estrdup(loc_name); return tag_value; } else { /* Since Grandfathered , no value , do nothing , retutn NULL */ return NULL; } } if( fromParseLocale==1 ){ /* Handle singletons */ if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ if( strlen(loc_name)>1 && (isIDPrefix(loc_name) ==1 ) ){ return loc_name; } } singletonPos = getSingletonPos( loc_name ); if( singletonPos == 0){ /* singleton at start of script, region , variant etc. * or invalid singleton at start of language */ return NULL; } else if( singletonPos > 0 ){ /* singleton at some position except at start * strip off the singleton and rest of the loc_name */ mod_loc_name = estrndup ( loc_name , singletonPos-1); } } /* end of if fromParse */ } /* end of if != LOC_CANONICAL_TAG */ if( mod_loc_name == NULL){ mod_loc_name = estrdup(loc_name ); } /* Proceed to ICU */ do{ tag_value = erealloc( tag_value , buflen ); tag_value_len = buflen; if( strcmp(tag_name , LOC_SCRIPT_TAG)==0 ){ buflen = uloc_getScript ( mod_loc_name ,tag_value , tag_value_len , &status); } if( strcmp(tag_name , LOC_LANG_TAG )==0 ){ buflen = uloc_getLanguage ( mod_loc_name ,tag_value , tag_value_len , &status); } if( strcmp(tag_name , LOC_REGION_TAG)==0 ){ buflen = uloc_getCountry ( mod_loc_name ,tag_value , tag_value_len , &status); } if( strcmp(tag_name , LOC_VARIANT_TAG)==0 ){ buflen = uloc_getVariant ( mod_loc_name ,tag_value , tag_value_len , &status); } if( strcmp(tag_name , LOC_CANONICALIZE_TAG)==0 ){ buflen = uloc_canonicalize ( mod_loc_name ,tag_value , tag_value_len , &status); } if( U_FAILURE( status ) ) { if( status == U_BUFFER_OVERFLOW_ERROR ) { status = U_ZERO_ERROR; continue; } /* Error in retriving data */ *result = 0; if( tag_value ){ efree( tag_value ); } if( mod_loc_name ){ efree( mod_loc_name); } return NULL; } } while( buflen > tag_value_len ); if( buflen ==0 ){ /* No value found */ *result = -1; if( tag_value ){ efree( tag_value ); } if( mod_loc_name ){ efree( mod_loc_name); } return NULL; } else { *result = 1; } if( mod_loc_name ){ efree( mod_loc_name); } return tag_value; }
/** * Create a tag string from the supplied parameters. The lang, script and region * parameters may be NULL pointers. If they are, their corresponding length parameters * must be less than or equal to 0. * * If any of the language, script or region parameters are empty, and the alternateTags * parameter is not NULL, it will be parsed for potential language, script and region tags * to be used when constructing the new tag. If the alternateTags parameter is NULL, or * it contains no language tag, the default tag for the unknown language is used. * * If the length of the new string exceeds the capacity of the output buffer, * the function copies as many bytes to the output buffer as it can, and returns * the error U_BUFFER_OVERFLOW_ERROR. * * If an illegal argument is provided, the function returns the error * U_ILLEGAL_ARGUMENT_ERROR. * * Note that this function can return the warning U_STRING_NOT_TERMINATED_WARNING if * the tag string fits in the output buffer, but the null terminator doesn't. * * @param lang The language tag to use. * @param langLength The length of the language tag. * @param script The script tag to use. * @param scriptLength The length of the script tag. * @param region The region tag to use. * @param regionLength The length of the region tag. * @param trailing Any trailing data to append to the new tag. * @param trailingLength The length of the trailing data. * @param alternateTags A string containing any alternate tags. * @param tag The output buffer. * @param tagCapacity The capacity of the output buffer. * @param err A pointer to a UErrorCode for error reporting. * @return The length of the tag string, which may be greater than tagCapacity, or -1 on error. **/ static int32_t U_CALLCONV createTagStringWithAlternates( const char* lang, int32_t langLength, const char* script, int32_t scriptLength, const char* region, int32_t regionLength, const char* trailing, int32_t trailingLength, const char* alternateTags, char* tag, int32_t tagCapacity, UErrorCode* err) { if (U_FAILURE(*err)) { goto error; } else if (tag == NULL || tagCapacity <= 0 || langLength >= ULOC_LANG_CAPACITY || scriptLength >= ULOC_SCRIPT_CAPACITY || regionLength >= ULOC_COUNTRY_CAPACITY) { goto error; } else { /** * ULOC_FULLNAME_CAPACITY will provide enough capacity * that we can build a string that contains the language, * script and region code without worrying about overrunning * the user-supplied buffer. **/ char tagBuffer[ULOC_FULLNAME_CAPACITY]; int32_t tagLength = 0; int32_t capacityRemaining = tagCapacity; UBool regionAppended = FALSE; if (langLength > 0) { appendTag( lang, langLength, tagBuffer, &tagLength); } else if (alternateTags == NULL) { /* * Append the value for an unknown language, if * we found no language. */ appendTag( unknownLanguage, (int32_t)uprv_strlen(unknownLanguage), tagBuffer, &tagLength); } else { /* * Parse the alternateTags string for the language. */ char alternateLang[ULOC_LANG_CAPACITY]; int32_t alternateLangLength = sizeof(alternateLang); alternateLangLength = uloc_getLanguage( alternateTags, alternateLang, alternateLangLength, err); if(U_FAILURE(*err) || alternateLangLength >= ULOC_LANG_CAPACITY) { goto error; } else if (alternateLangLength == 0) { /* * Append the value for an unknown language, if * we found no language. */ appendTag( unknownLanguage, (int32_t)uprv_strlen(unknownLanguage), tagBuffer, &tagLength); } else { appendTag( alternateLang, alternateLangLength, tagBuffer, &tagLength); } } if (scriptLength > 0) { appendTag( script, scriptLength, tagBuffer, &tagLength); } else if (alternateTags != NULL) { /* * Parse the alternateTags string for the script. */ char alternateScript[ULOC_SCRIPT_CAPACITY]; const int32_t alternateScriptLength = uloc_getScript( alternateTags, alternateScript, sizeof(alternateScript), err); if (U_FAILURE(*err) || alternateScriptLength >= ULOC_SCRIPT_CAPACITY) { goto error; } else if (alternateScriptLength > 0) { appendTag( alternateScript, alternateScriptLength, tagBuffer, &tagLength); } } if (regionLength > 0) { appendTag( region, regionLength, tagBuffer, &tagLength); regionAppended = TRUE; } else if (alternateTags != NULL) { /* * Parse the alternateTags string for the region. */ char alternateRegion[ULOC_COUNTRY_CAPACITY]; const int32_t alternateRegionLength = uloc_getCountry( alternateTags, alternateRegion, sizeof(alternateRegion), err); if (U_FAILURE(*err) || alternateRegionLength >= ULOC_COUNTRY_CAPACITY) { goto error; } else if (alternateRegionLength > 0) { appendTag( alternateRegion, alternateRegionLength, tagBuffer, &tagLength); regionAppended = TRUE; } } { const int32_t toCopy = tagLength >= tagCapacity ? tagCapacity : tagLength; /** * Copy the partial tag from our internal buffer to the supplied * target. **/ uprv_memcpy( tag, tagBuffer, toCopy); capacityRemaining -= toCopy; } if (trailingLength > 0) { if (*trailing != '@' && capacityRemaining > 0) { tag[tagLength++] = '_'; --capacityRemaining; if (capacityRemaining > 0 && !regionAppended) { /* extra separator is required */ tag[tagLength++] = '_'; --capacityRemaining; } } if (capacityRemaining > 0) { /* * Copy the trailing data into the supplied buffer. Use uprv_memmove, since we * don't know if the user-supplied buffers overlap. */ const int32_t toCopy = trailingLength >= capacityRemaining ? capacityRemaining : trailingLength; uprv_memmove( &tag[tagLength], trailing, toCopy); } } tagLength += trailingLength; return u_terminateChars( tag, tagCapacity, tagLength, err); } error: /** * An overflow indicates the locale ID passed in * is ill-formed. If we got here, and there was * no previous error, it's an implicit overflow. **/ if (*err == U_BUFFER_OVERFLOW_ERROR || U_SUCCESS(*err)) { *err = U_ILLEGAL_ARGUMENT_ERROR; } return -1; }
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); }