ICU-5794 1. Fixed warnings. 2. Add mutex for hash table read. 3. Add more comments.

X-SVN-Rev: 23274
This commit is contained in:
Claire Ho 2008-01-20 02:30:30 +00:00
parent fdf0256d94
commit 89fd440ebc
3 changed files with 85 additions and 51 deletions

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and
* Copyright (C) 2008, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
@ -16,7 +16,6 @@
#include "unicode/utypes.h"
#include "unicode/plurfmt.h"
#include "unicode/plurrule.h"
#include "mutex.h"
#include "plurrule_impl.h"
#if !UCONFIG_NO_FORMATTING
@ -60,12 +59,12 @@ PluralFormat::PluralFormat(const Locale& locale, const UnicodeString& pattern, U
}
PluralFormat::PluralFormat(const PluralRules& rules, const UnicodeString& pattern, UErrorCode& status) {
init(NULL, locale, status);
init(&rules, locale, status);
applyPattern(pattern, status);
}
PluralFormat::PluralFormat(const Locale& locale, const PluralRules& rules, const UnicodeString& pattern, UErrorCode& status) {
init(NULL, locale, status);
init(&rules, locale, status);
applyPattern(pattern, status);
}
@ -109,7 +108,6 @@ PluralFormat::applyPattern(const UnicodeString& newPattern, UErrorCode& status)
UBool spaceIncluded=FALSE;
if (fParsedValuesHash==NULL) {
Mutex mutex;
fParsedValuesHash = new Hashtable(TRUE, status);
if (U_FAILURE(status)) {
return;
@ -257,7 +255,7 @@ UnicodeString&
PluralFormat::format(int32_t number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& status) const {
UErrorCode& /*status*/) const {
if (fParsedValuesHash==NULL) {
if ( replacedNumberFormat== NULL ) {
@ -343,7 +341,7 @@ PluralFormat::setLocale(const Locale& locale, UErrorCode& status) {
}
void
PluralFormat::setNumberFormat(const NumberFormat* format, UErrorCode& status) {
PluralFormat::setNumberFormat(const NumberFormat* format, UErrorCode& /*status*/) {
// TODO: The copy constructor and assignment op of NumberFormat class are protected.
// create a pointer as the workaround.
replacedNumberFormat = (NumberFormat *)format;
@ -378,9 +376,9 @@ PluralFormat::operator!=(const Format& other) const {
}
void
PluralFormat::parseObject(const UnicodeString& source,
Formattable& result,
ParsePosition& pos) const
PluralFormat::parseObject(const UnicodeString& /*source*/,
Formattable& /*result*/,
ParsePosition& /*pos*/) const
{
// TODO: not yet supported in icu4j and icu4c
}

View file

@ -19,13 +19,39 @@
#include "cmemory.h"
#include "cstring.h"
#include "hash.h"
#include "mutex.h"
#include "ucln_in.h"
#include "umutex.h"
#include "plurrule_impl.h"
#include "putilimp.h"
#include "ustrfmt.h"
#if !UCONFIG_NO_FORMATTING
// gPluralRuleLocaleHash is a global hash table that maps locale name to
// the pointer of PluralRule. gPluralRuleLocaleHash is built only once and
// destroried at end of application. We don't need the gPluralRuleLocaleHash
// when we move plural rules data to resource bundle in ICU4.x release.
static UMTX pRulesLock = 0;
static Hashtable *gPluralRuleLocaleHash=NULL;
U_CDECL_BEGIN
static void U_CALLCONV
deletePHashRules(void *obj) {
delete (RuleChain *)obj;
}
static UBool plural_rules_cleanup(void) {
if (gPluralRuleLocaleHash) {
delete gPluralRuleLocaleHash;
gPluralRuleLocaleHash = NULL;
}
umtx_destroy(&pRulesLock);
return TRUE;
}
U_CDECL_END
U_NAMESPACE_BEGIN
// TODO: Plural rule data - will move to ResourceBundle.
@ -96,7 +122,6 @@ static const UChar uCharPluralRules[NUMBER_PLURAL_RULES][128] = {
LOW_R, 0},
};
static Hashtable *gPluralRuleLocaleHash=NULL;
static const UChar PLURAL_KEYWORD_ZERO[] = {LOW_Z,LOW_E,LOW_R,LOW_O, 0};
static const UChar PLURAL_KEYWORD_ONE[]={LOW_O,LOW_N,LOW_E,0};
static const UChar PLURAL_KEYWORD_TWO[]={LOW_T,LOW_W,LOW_O,0};
@ -125,7 +150,7 @@ PluralRules::PluralRules(UErrorCode& status) {
}
}
PluralRules::PluralRules(const PluralRules& other)
PluralRules::PluralRules(const PluralRules& other)
: UObject(other)
{
*this=other;
@ -136,7 +161,6 @@ PluralRules::~PluralRules() {
delete parser;
}
PluralRules*
PluralRules::clone() const {
return new PluralRules(*this);
@ -147,14 +171,14 @@ PluralRules::operator=(const PluralRules& other) {
fLocaleStringsHash=other.fLocaleStringsHash;
rules = new RuleChain(*other.rules);
parser = new RuleParser();
return *this;
}
PluralRules* U_EXPORT2
PluralRules::createRules(const UnicodeString& description, UErrorCode& status) {
RuleChain rules;
PluralRules *newRules = new PluralRules(status);
if ( (newRules != NULL)&& U_SUCCESS(status) ) {
newRules->parseDescription((UnicodeString &)description, rules, status);
@ -186,7 +210,9 @@ PluralRules::forLocale(const Locale& locale, UErrorCode& status) {
return NULL;
}
UnicodeString localeName(locale.getName());
umtx_lock(&pRulesLock);
locRules = (RuleChain *) (newRules->fLocaleStringsHash->get(localeName));
umtx_unlock(&pRulesLock);
if (locRules == NULL) {
// Check parent locales.
char parentLocale[ULOC_FULLNAME_CAPACITY];
@ -194,7 +220,9 @@ PluralRules::forLocale(const Locale& locale, UErrorCode& status) {
int32_t localeNameLen=0;
uprv_strcpy(parentLocale, curLocaleName);
while ((localeNameLen=uloc_getParent(parentLocale, parentLocale, ULOC_FULLNAME_CAPACITY, &status)) > 0) {
umtx_lock(&pRulesLock);
locRules = (RuleChain *) (newRules->fLocaleStringsHash->get(localeName));
umtx_unlock(&pRulesLock);
if (locRules != NULL) {
break;
}
@ -244,7 +272,6 @@ PluralRules::isKeyword(const UnicodeString& keyword) const {
UnicodeString
PluralRules::getKeywordOther() const {
return PLURAL_KEYWORD_OTHER;
}
UBool
@ -253,13 +280,13 @@ PluralRules::operator==(const PluralRules& other) const {
UBool sameList = TRUE;
const UnicodeString *ptrKeyword;
UErrorCode status= U_ZERO_ERROR;
if ( this == &other ) {
return TRUE;
}
StringEnumeration* myKeywordList = getKeywords(status);
StringEnumeration* otherKeywordList =other.getKeywords(status);
if (myKeywordList->count(status)!=otherKeywordList->count(status)) {
sameList = FALSE;
}
@ -282,7 +309,7 @@ PluralRules::operator==(const PluralRules& other) const {
return FALSE;
}
}
if ((limit=this->getRepeatLimit()) != other.getRepeatLimit()) {
return FALSE;
}
@ -297,7 +324,7 @@ PluralRules::operator==(const PluralRules& other) const {
return TRUE;
}
void
void
PluralRules::getRuleData(UErrorCode& status) {
UnicodeString ruleData;
UnicodeString localeData;
@ -335,7 +362,7 @@ PluralRules::parseDescription(UnicodeString& data, RuleChain& rules, UErrorCode
RuleChain *ruleChain=NULL;
AndConstraint *curAndConstraint=NULL;
OrConstraint *orNode=NULL;
UnicodeString ruleData = data.toLower();
while (ruleIndex< ruleData.length()) {
parser->getNextToken(ruleData, &ruleIndex, token, type, status);
@ -370,7 +397,7 @@ PluralRules::parseDescription(UnicodeString& data, RuleChain& rules, UErrorCode
curAndConstraint->rangeHigh=PLURAL_RANGE_HIGH;
break;
case tNumber:
if ( (curAndConstraint->op==AndConstraint::MOD)&&
if ( (curAndConstraint->op==AndConstraint::MOD)&&
(curAndConstraint->opNum == -1 ) ) {
curAndConstraint->opNum=getNumberValue(token);
}
@ -400,12 +427,14 @@ PluralRules::parseDescription(UnicodeString& data, RuleChain& rules, UErrorCode
curAndConstraint = orNode->add();
ruleChain->keyword = token;
break;
default:
break;
}
prevType=type;
}
}
int32_t
int32_t
PluralRules::getNumberValue(const UnicodeString& token) const {
int32_t i;
char digits[128];
@ -414,7 +443,7 @@ PluralRules::getNumberValue(const UnicodeString& token) const {
digits[i]=(char)token.charAt(i);
}
digits[i]='\0';
return((int32_t)atoi(digits));
}
@ -422,16 +451,15 @@ PluralRules::getNumberValue(const UnicodeString& token) const {
void
PluralRules::getNextLocale(const UnicodeString& localeData, int32_t* curIndex, UnicodeString& localeName) {
int32_t i=*curIndex;
localeName.remove();
while (i< localeData.length()) {
if ( (localeData.charAt(i)!= SPACE) && (localeData.charAt(i)!= COMMA) ) {
break;
}
i++;
}
while (i< localeData.length()) {
if ( (localeData.charAt(i)== SPACE) || (localeData.charAt(i)== COMMA) ) {
break;
@ -447,41 +475,49 @@ PluralRules::getRepeatLimit() const {
return rules->getRepeatLimit();
}
void
void
PluralRules::initHashtable(UErrorCode& status) {
if (fLocaleStringsHash!=NULL) {
return;
}
if ( gPluralRuleLocaleHash == NULL ) {
Mutex mutex;
UBool needsInit;
UMTX_CHECK(&LOCK, (gPluralRuleLocaleHash == NULL), needsInit);/* This is here to prevent race conditions. */
if (needsInit) {
// This static PluralRule hashtable residents in memory until end of application.
umtx_lock(&pRulesLock);
if ((gPluralRuleLocaleHash = new Hashtable(TRUE, status))!=NULL) {
ucln_i18n_registerCleanup(UCLN_I18N_PLURAL_RULE, plural_rules_cleanup);
gPluralRuleLocaleHash->setValueDeleter(deletePHashRules);
fLocaleStringsHash = gPluralRuleLocaleHash;
umtx_unlock(&pRulesLock);
return;
}
umtx_unlock(&pRulesLock);
}
else {
fLocaleStringsHash = gPluralRuleLocaleHash;
}
}
void
void
PluralRules::addRules(RuleChain& rules, UErrorCode& status) {
addRules(localeName, rules, FALSE, status);
}
void
void
PluralRules::addRules(const UnicodeString& localeName, RuleChain& rules, UBool addToHash, UErrorCode& status) {
RuleChain *newRule = new RuleChain(rules);
if ( addToHash )
{
{
Mutex mutex;
{
umtx_lock(&pRulesLock);
if ( (RuleChain *)fLocaleStringsHash->get(localeName) == NULL ) {
fLocaleStringsHash->put(localeName, newRule, status);
this->rules=newRule;
umtx_unlock(&pRulesLock);
}
else {
umtx_unlock(&pRulesLock);
delete newRule;
return;
}
@ -620,8 +656,6 @@ OrConstraint::add()
{
OrConstraint *curOrConstraint=this;
{
Mutex mutex;
while (curOrConstraint->next!=NULL) {
curOrConstraint = curOrConstraint->next;
}
@ -728,7 +762,6 @@ RuleChain::dumpRules(UnicodeString& result) {
else {
result += UNICODE_STRING_SIMPLE(" n ");
}
if (andRule->rangeHigh==-1) {
if (andRule->notIn) {
result += UNICODE_STRING_SIMPLE(" is not ");
@ -759,7 +792,6 @@ RuleChain::dumpRules(UnicodeString& result) {
}
}
}
if ( (andRule=andRule->next) != NULL) {
result += PK_AND;
}
@ -769,7 +801,6 @@ RuleChain::dumpRules(UnicodeString& result) {
}
}
}
if ( next != NULL ) {
next->dumpRules(result);
}
@ -783,12 +814,12 @@ RuleChain::getRepeatLimit () {
void
RuleChain::setRepeatLimit () {
int32_t limit=0;
if ( next != NULL ) {
next->setRepeatLimit();
limit = next->repeatLimit;
}
if ( ruleHeader != NULL ) {
OrConstraint* orRule=ruleHeader;
while ( orRule != NULL ) {
@ -800,7 +831,6 @@ RuleChain::setRepeatLimit () {
orRule = orRule->next;
}
}
repeatLimit = limit;
}
@ -812,7 +842,7 @@ RuleChain::getKeywords(int32_t capacityOfKeywords, UnicodeString* keywords, int3
else {
return U_BUFFER_OVERFLOW_ERROR;
}
if ( next != NULL ) {
return next->getKeywords(capacityOfKeywords, keywords, arraySize);
}
@ -826,7 +856,7 @@ RuleChain::isKeyword(const UnicodeString& keyword) const {
if ( this->keyword == keyword ) {
return TRUE;
}
if ( next != NULL ) {
return next->isKeyword(keyword);
}
@ -862,7 +892,7 @@ RuleParser::checkSyntax(tokenType prevType, tokenType curType, UErrorCode &statu
status = U_UNEXPECTED_TOKEN;
}
break;
case tVariableN :
case tVariableN :
if (curType != tIs && curType != tMod && curType != tIn && curType != tNot) {
status = U_UNEXPECTED_TOKEN;
}
@ -903,7 +933,7 @@ RuleParser::checkSyntax(tokenType prevType, tokenType curType, UErrorCode &statu
}
break;
case tNumber:
if (curType != tDot && curType != tSemiColon && curType != tIs && curType != tNot &&
if (curType != tDot && curType != tSemiColon && curType != tIs && curType != tNot &&
curType != tIn && curType != tAnd && curType != tOr)
{
status = U_UNEXPECTED_TOKEN;
@ -916,7 +946,7 @@ RuleParser::checkSyntax(tokenType prevType, tokenType curType, UErrorCode &statu
}
void
RuleParser::getNextToken(const UnicodeString& ruleData,
RuleParser::getNextToken(const UnicodeString& ruleData,
int32_t *ruleIndex,
UnicodeString& token,
tokenType& type,
@ -925,7 +955,7 @@ RuleParser::getNextToken(const UnicodeString& ruleData,
int32_t curIndex= *ruleIndex;
UChar ch;
tokenType prevType=none;
while (curIndex<ruleData.length()) {
ch = ruleData.charAt(curIndex);
if ( !inRange(ch, type) ) {
@ -963,6 +993,7 @@ RuleParser::getNextToken(const UnicodeString& ruleData,
prevType=type;
break;
}
break;
case tNumber:
if ((type==prevType)||(prevType==none)) {
prevType=type;
@ -990,6 +1021,10 @@ RuleParser::getNextToken(const UnicodeString& ruleData,
return;
}
}
break;
default:
status = U_UNEXPECTED_TOKEN;
return;
}
curIndex++;
}
@ -1017,7 +1052,7 @@ RuleParser::inRange(UChar ch, tokenType& type) {
return TRUE;
}
switch (ch) {
case COLON:
case COLON:
type = tColon;
return TRUE;
case SPACE:

View file

@ -42,6 +42,7 @@ typedef enum ECleanupI18NType {
UCLN_I18N_CSDET,
UCLN_I18N_ZONEMETA,
UCLN_I18N_ZSFORMAT,
UCLN_I18N_PLURAL_RULE,
UCLN_I18N_COUNT /* This must be last */
} ECleanupI18NType;