mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 23:10:40 +00:00
ICU-10681 Lazily get and cache BreakIterator for titlecasing; lazily get contextTransform info if possible (C)
X-SVN-Rev: 35287
This commit is contained in:
parent
11676f470f
commit
27cfaed4d8
8 changed files with 242 additions and 146 deletions
|
@ -12,6 +12,7 @@
|
|||
#include "unicode/locdspnm.h"
|
||||
#include "unicode/msgfmt.h"
|
||||
#include "unicode/ures.h"
|
||||
#include "unicode/udisplaycontext.h"
|
||||
#include "unicode/brkiter.h"
|
||||
|
||||
#include "cmemory.h"
|
||||
|
@ -275,6 +276,7 @@ class LocaleDisplayNamesImpl : public LocaleDisplayNames {
|
|||
MessageFormat *format;
|
||||
MessageFormat *keyTypeFormat;
|
||||
UDisplayContext capitalizationContext;
|
||||
BreakIterator* capitalizationBrkIter;
|
||||
UnicodeString formatOpenParen;
|
||||
UnicodeString formatReplaceOpenParen;
|
||||
UnicodeString formatCloseParen;
|
||||
|
@ -290,10 +292,9 @@ class LocaleDisplayNamesImpl : public LocaleDisplayNames {
|
|||
kCapContextUsageKeyValue,
|
||||
kCapContextUsageCount
|
||||
};
|
||||
// Capitalization transforms. For each usage type, the first array element indicates
|
||||
// whether to titlecase for uiListOrMenu context, the second indicates whether to
|
||||
// titlecase for stand-alone context.
|
||||
UBool fCapitalization[kCapContextUsageCount][2];
|
||||
// Capitalization transforms. For each usage type, indicates whether to titlecase for
|
||||
// the context specified in capitalizationContext (which we know at construction time)
|
||||
UBool fCapitalization[kCapContextUsageCount];
|
||||
|
||||
public:
|
||||
// constructor
|
||||
|
@ -341,6 +342,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
|
|||
, format(NULL)
|
||||
, keyTypeFormat(NULL)
|
||||
, capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
||||
, capitalizationBrkIter(NULL)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
@ -354,6 +356,7 @@ LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale,
|
|||
, format(NULL)
|
||||
, keyTypeFormat(NULL)
|
||||
, capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
|
||||
, capitalizationBrkIter(NULL)
|
||||
{
|
||||
while (length-- > 0) {
|
||||
UDisplayContext value = *contexts++;
|
||||
|
@ -429,35 +432,52 @@ LocaleDisplayNamesImpl::initialize(void) {
|
|||
{ "variant", kCapContextUsageVariant },
|
||||
{ NULL, (CapContextUsage)0 },
|
||||
};
|
||||
int32_t len = 0;
|
||||
UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, "contextTransforms", NULL, &status);
|
||||
// Only get the context data if we need it! This is a const object so we know now...
|
||||
// Also check whether we will need a break iterator (depends on the data)
|
||||
UBool needBrkIter = FALSE;
|
||||
if (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_STANDALONE) {
|
||||
int32_t len = 0;
|
||||
UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
UResourceBundle *contextTransformUsage;
|
||||
while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &status)) != NULL ) {
|
||||
const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
|
||||
if (U_SUCCESS(status) && intVector != NULL && len >= 2) {
|
||||
const char* usageKey = ures_getKey(contextTransformUsage);
|
||||
if (usageKey != NULL) {
|
||||
const ContextUsageNameToEnum * typeMapPtr = contextUsageTypeMap;
|
||||
int32_t compResult = 0;
|
||||
// linear search; list is short and we cannot be sure that bsearch is available
|
||||
while ( typeMapPtr->usageName != NULL && (compResult = uprv_strcmp(usageKey, typeMapPtr->usageName)) > 0 ) {
|
||||
++typeMapPtr;
|
||||
}
|
||||
if (typeMapPtr->usageName != NULL && compResult == 0) {
|
||||
fCapitalization[typeMapPtr->usageEnum][0] = intVector[0];
|
||||
fCapitalization[typeMapPtr->usageEnum][1] = intVector[1];
|
||||
UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, "contextTransforms", NULL, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
UResourceBundle *contextTransformUsage;
|
||||
while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &status)) != NULL ) {
|
||||
const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
|
||||
if (U_SUCCESS(status) && intVector != NULL && len >= 2) {
|
||||
const char* usageKey = ures_getKey(contextTransformUsage);
|
||||
if (usageKey != NULL) {
|
||||
const ContextUsageNameToEnum * typeMapPtr = contextUsageTypeMap;
|
||||
int32_t compResult = 0;
|
||||
// linear search; list is short and we cannot be sure that bsearch is available
|
||||
while ( typeMapPtr->usageName != NULL && (compResult = uprv_strcmp(usageKey, typeMapPtr->usageName)) > 0 ) {
|
||||
++typeMapPtr;
|
||||
}
|
||||
if (typeMapPtr->usageName != NULL && compResult == 0) {
|
||||
int32_t titlecaseInt = (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU)? intVector[0]: intVector[1];
|
||||
if (titlecaseInt != 0) {
|
||||
fCapitalization[typeMapPtr->usageEnum] = TRUE;;
|
||||
needBrkIter = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
status = U_ZERO_ERROR;
|
||||
ures_close(contextTransformUsage);
|
||||
}
|
||||
status = U_ZERO_ERROR;
|
||||
ures_close(contextTransformUsage);
|
||||
ures_close(contextTransforms);
|
||||
}
|
||||
ures_close(contextTransforms);
|
||||
ures_close(localeBundle);
|
||||
}
|
||||
}
|
||||
// Get a sentence break iterator if we will need it
|
||||
if (needBrkIter || capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE) {
|
||||
status = U_ZERO_ERROR;
|
||||
capitalizationBrkIter = BreakIterator::createSentenceInstance(locale, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete capitalizationBrkIter;
|
||||
capitalizationBrkIter = NULL;
|
||||
}
|
||||
ures_close(localeBundle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -466,6 +486,7 @@ LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() {
|
|||
delete separatorFormat;
|
||||
delete format;
|
||||
delete keyTypeFormat;
|
||||
delete capitalizationBrkIter;
|
||||
}
|
||||
|
||||
const Locale&
|
||||
|
@ -496,51 +517,10 @@ LocaleDisplayNamesImpl::adjustForUsageAndContext(CapContextUsage usage,
|
|||
UnicodeString& result) const {
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
// check to see whether we need to titlecase result
|
||||
UBool titlecase = FALSE;
|
||||
switch (capitalizationContext) {
|
||||
case UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE:
|
||||
titlecase = TRUE;
|
||||
break;
|
||||
case UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU:
|
||||
titlecase = fCapitalization[usage][0];
|
||||
break;
|
||||
case UDISPCTX_CAPITALIZATION_FOR_STANDALONE:
|
||||
titlecase = fCapitalization[usage][1];
|
||||
break;
|
||||
default:
|
||||
// titlecase = FALSE;
|
||||
break;
|
||||
}
|
||||
if (titlecase) {
|
||||
// TODO: Fix this titlecase hack when we figure out something better to do.
|
||||
// We don't want to titlecase the whole text, only something like the first word,
|
||||
// of the first segment long enough to have a complete cluster, whichever is
|
||||
// shorter. We could have keep a word break iterator around, but I am not sure
|
||||
// that will do the ight thing for the purposes here. For now we assume that in
|
||||
// languages for which titlecasing makes a difference, we can stop at non-letter
|
||||
// characters in 0x0000-0x00FF and only titlecase up to the first occurrence of
|
||||
// any of those, or to a small number of chars, whichever comes first.
|
||||
int32_t stopPos, stopPosLimit = 8, len = result.length();
|
||||
if ( stopPosLimit > len ) {
|
||||
stopPosLimit = len;
|
||||
}
|
||||
for ( stopPos = 0; stopPos < stopPosLimit; stopPos++ ) {
|
||||
UChar32 ch = result.char32At(stopPos);
|
||||
if ( (ch < 0x41) || (ch > 0x5A && ch < 0x61) || (ch > 0x7A && ch < 0xC0) ) {
|
||||
break;
|
||||
}
|
||||
if (ch >= 0x10000) {
|
||||
stopPos++;
|
||||
}
|
||||
}
|
||||
if ( stopPos > 0 && stopPos < len ) {
|
||||
UnicodeString firstWord(result, 0, stopPos);
|
||||
firstWord.toTitle(NULL, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
result.replaceBetween(0, stopPos, firstWord);
|
||||
} else {
|
||||
// no stopPos, titlecase the whole text
|
||||
result.toTitle(NULL, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
}
|
||||
if ( result.length() > 0 && u_islower(result.char32At(0)) && capitalizationBrkIter!= NULL &&
|
||||
( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || fCapitalization[usage] ) ) {
|
||||
// note fCapitalization[usage] won't be set unless capitalizationContext is UI_LIST_OR_MENU or STANDALONE
|
||||
result.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
|
|
|
@ -1519,6 +1519,10 @@ RuleBasedNumberFormat::setContext(UDisplayContext value, UErrorCode& status)
|
|||
(value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone)) ) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
capitalizationBrkIter = BreakIterator::createSentenceInstance(locale, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete capitalizationBrkIter;
|
||||
capitalizationBrkIter = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "unicode/msgfmt.h"
|
||||
#include "unicode/udisplaycontext.h"
|
||||
#include "unicode/uchar.h"
|
||||
#include "unicode/brkiter.h"
|
||||
|
||||
#include "gregoimp.h" // for CalendarData
|
||||
#include "cmemory.h"
|
||||
|
@ -45,7 +46,11 @@ RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) :
|
|||
fDateStyle(other.fDateStyle), fLocale(other.fLocale),
|
||||
fDayMin(other.fDayMin), fDayMax(other.fDayMax),
|
||||
fDatesLen(other.fDatesLen), fDates(NULL),
|
||||
fCombinedHasDateAtStart(other.fCombinedHasDateAtStart)
|
||||
fCombinedHasDateAtStart(other.fCombinedHasDateAtStart),
|
||||
fCapitalizationInfoSet(other.fCapitalizationInfoSet),
|
||||
fCapitalizationOfRelativeUnitsForUIListMenu(other.fCapitalizationOfRelativeUnitsForUIListMenu),
|
||||
fCapitalizationOfRelativeUnitsForStandAlone(other.fCapitalizationOfRelativeUnitsForStandAlone),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
if(other.fDateTimeFormatter != NULL) {
|
||||
fDateTimeFormatter = (SimpleDateFormat*)other.fDateTimeFormatter->clone();
|
||||
|
@ -57,15 +62,18 @@ RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) :
|
|||
fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
|
||||
uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*fDatesLen);
|
||||
}
|
||||
fCapitalizationForRelativeUnits[0] = other.fCapitalizationForRelativeUnits[0];
|
||||
fCapitalizationForRelativeUnits[1] = other.fCapitalizationForRelativeUnits[1];
|
||||
if (other.fCapitalizationBrkIter != NULL) {
|
||||
fCapitalizationBrkIter = (other.fCapitalizationBrkIter)->clone();
|
||||
}
|
||||
}
|
||||
|
||||
RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatStyle dateStyle,
|
||||
const Locale& locale, UErrorCode& status) :
|
||||
DateFormat(), fDateTimeFormatter(NULL), fDatePattern(), fTimePattern(), fCombinedFormat(NULL),
|
||||
fDateStyle(dateStyle), fLocale(locale), fDayMin(0), fDayMax(0), fDatesLen(0), fDates(NULL),
|
||||
fCombinedHasDateAtStart(FALSE)
|
||||
fCombinedHasDateAtStart(FALSE), fCapitalizationInfoSet(FALSE),
|
||||
fCapitalizationOfRelativeUnitsForUIListMenu(FALSE), fCapitalizationOfRelativeUnitsForStandAlone(FALSE),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
if(U_FAILURE(status) ) {
|
||||
return;
|
||||
|
@ -116,6 +124,7 @@ RelativeDateFormat::~RelativeDateFormat() {
|
|||
delete fDateTimeFormatter;
|
||||
delete fCombinedFormat;
|
||||
uprv_free(fDates);
|
||||
delete fCapitalizationBrkIter;
|
||||
}
|
||||
|
||||
|
||||
|
@ -125,6 +134,8 @@ Format* RelativeDateFormat::clone(void) const {
|
|||
|
||||
UBool RelativeDateFormat::operator==(const Format& other) const {
|
||||
if(DateFormat::operator==(other)) {
|
||||
// The DateFormat::operator== check for fCapitalizationContext equality above
|
||||
// is sufficient to check equality of all derived context-related data.
|
||||
// DateFormat::operator== guarantees following cast is safe
|
||||
RelativeDateFormat* that = (RelativeDateFormat*)&other;
|
||||
return (fDateStyle==that->fDateStyle &&
|
||||
|
@ -158,34 +169,16 @@ UnicodeString& RelativeDateFormat::format( Calendar& cal,
|
|||
|
||||
if ( relativeDayString.length() > 0 && !fDatePattern.isEmpty() &&
|
||||
(fTimePattern.isEmpty() || fCombinedFormat == NULL || fCombinedHasDateAtStart)) {
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
// capitalize relativeDayString according to context for relative, set formatter no context
|
||||
if ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
||||
(capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationForRelativeUnits[0]) ||
|
||||
(capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationForRelativeUnits[1]) ) {
|
||||
// titlecase first word of relativeDayString, do like LocaleDisplayNamesImpl::adjustForUsageAndContext
|
||||
int32_t stopPos, stopPosLimit = 8;
|
||||
if ( stopPosLimit > len ) {
|
||||
stopPosLimit = len;
|
||||
}
|
||||
for ( stopPos = 0; stopPos < stopPosLimit; stopPos++ ) {
|
||||
UChar32 ch = relativeDayString.char32At(stopPos);
|
||||
int32_t wb = u_getIntPropertyValue(ch, UCHAR_WORD_BREAK);
|
||||
if (!(u_islower(ch) || wb==U_WB_EXTEND || wb==U_WB_SINGLE_QUOTE || wb==U_WB_MIDNUMLET || wb==U_WB_MIDLETTER)) {
|
||||
break;
|
||||
}
|
||||
if (ch >= 0x10000) {
|
||||
stopPos++;
|
||||
}
|
||||
}
|
||||
if ( stopPos > 0 && stopPos < len ) {
|
||||
UnicodeString firstWord(relativeDayString, 0, stopPos);
|
||||
firstWord.toTitle(NULL, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
relativeDayString.replaceBetween(0, stopPos, firstWord);
|
||||
} else {
|
||||
// no stopPos, titlecase the whole text
|
||||
relativeDayString.toTitle(NULL, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
}
|
||||
if ( u_islower(relativeDayString.char32At(0)) && fCapitalizationBrkIter!= NULL &&
|
||||
( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
||||
(capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationOfRelativeUnitsForUIListMenu) ||
|
||||
(capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationOfRelativeUnitsForStandAlone) ) ) {
|
||||
// titlecase first word of relativeDayString
|
||||
relativeDayString.toTitle(fCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
}
|
||||
#endif
|
||||
fDateTimeFormatter->setContext(UDISPCTX_CAPITALIZATION_NONE, status);
|
||||
} else {
|
||||
// set our context for the formatter
|
||||
|
@ -427,6 +420,54 @@ RelativeDateFormat::getDateFormatSymbols() const
|
|||
return fDateTimeFormatter->getDateFormatSymbols();
|
||||
}
|
||||
|
||||
// override the DateFormat implementation in order to
|
||||
// lazily initialize relevant items
|
||||
void
|
||||
RelativeDateFormat::setContext(UDisplayContext value, UErrorCode& status)
|
||||
{
|
||||
DateFormat::setContext(value, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
if (!fCapitalizationInfoSet &&
|
||||
(value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE)) {
|
||||
initCapitalizationContextInfo(fLocale);
|
||||
fCapitalizationInfoSet = TRUE;
|
||||
}
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
if ( fCapitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
||||
(value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationOfRelativeUnitsForUIListMenu) ||
|
||||
(value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationOfRelativeUnitsForStandAlone)) ) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fCapitalizationBrkIter = BreakIterator::createSentenceInstance(fLocale, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete fCapitalizationBrkIter;
|
||||
fCapitalizationBrkIter = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RelativeDateFormat::initCapitalizationContextInfo(const Locale& thelocale)
|
||||
{
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
const char * localeID = (thelocale != NULL)? thelocale.getBaseName(): NULL;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UResourceBundle *rb = ures_open(NULL, localeID, &status);
|
||||
rb = ures_getByKeyWithFallback(rb, "contextTransforms", rb, &status);
|
||||
rb = ures_getByKeyWithFallback(rb, "relative", rb, &status);
|
||||
if (U_SUCCESS(status) && rb != NULL) {
|
||||
int32_t len = 0;
|
||||
const int32_t * intVector = ures_getIntVector(rb, &len, &status);
|
||||
if (U_SUCCESS(status) && intVector != NULL && len >= 2) {
|
||||
fCapitalizationOfRelativeUnitsForUIListMenu = intVector[0];
|
||||
fCapitalizationOfRelativeUnitsForStandAlone = intVector[1];
|
||||
}
|
||||
}
|
||||
ures_close(rb);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const UChar patItem1[] = {0x7B,0x31,0x7D}; // "{1}"
|
||||
static const int32_t patItem1Len = 3;
|
||||
|
||||
|
@ -473,35 +514,21 @@ void RelativeDateFormat::loadDates(UErrorCode &status) {
|
|||
}
|
||||
}
|
||||
|
||||
fCapitalizationForRelativeUnits[0] = fCapitalizationForRelativeUnits[1] = FALSE;
|
||||
UResourceBundle *lb = ures_open(NULL, fLocale.getBaseName(), &status);
|
||||
tempStatus = status;
|
||||
UResourceBundle *rb = ures_getByKeyWithFallback(lb, "contextTransforms", NULL, &tempStatus);
|
||||
UResourceBundle *sb = ures_getByKeyWithFallback(rb, "relative", NULL, &tempStatus);
|
||||
if (U_SUCCESS(tempStatus) && sb != NULL) {
|
||||
int32_t len = 0;
|
||||
const int32_t * intVector = ures_getIntVector(sb, &len, &tempStatus);
|
||||
if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
|
||||
fCapitalizationForRelativeUnits[0] = intVector[0];
|
||||
fCapitalizationForRelativeUnits[1] = intVector[1];
|
||||
}
|
||||
}
|
||||
sb = ures_getByKeyWithFallback(lb, "fields", sb, &status);
|
||||
rb = ures_getByKeyWithFallback(sb, "day", rb, &status);
|
||||
sb = ures_getByKeyWithFallback(rb, "relative", sb, &status);
|
||||
ures_close(rb);
|
||||
ures_close(lb);
|
||||
UResourceBundle *rb = ures_open(NULL, fLocale.getBaseName(), &status);
|
||||
rb = ures_getByKeyWithFallback(rb, "fields", rb, &status);
|
||||
rb = ures_getByKeyWithFallback(rb, "day", rb, &status);
|
||||
rb = ures_getByKeyWithFallback(rb, "relative", rb, &status);
|
||||
// set up min/max
|
||||
fDayMin=-1;
|
||||
fDayMax=1;
|
||||
|
||||
if(U_FAILURE(status)) {
|
||||
fDatesLen=0;
|
||||
ures_close(sb);
|
||||
ures_close(rb);
|
||||
return;
|
||||
}
|
||||
|
||||
fDatesLen = ures_getSize(sb);
|
||||
fDatesLen = ures_getSize(rb);
|
||||
fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
|
||||
|
||||
// Load in each item into the array...
|
||||
|
@ -509,8 +536,8 @@ void RelativeDateFormat::loadDates(UErrorCode &status) {
|
|||
|
||||
UResourceBundle *subString = NULL;
|
||||
|
||||
while(ures_hasNext(sb) && U_SUCCESS(status)) { // iterate over items
|
||||
subString = ures_getNextResource(sb, subString, &status);
|
||||
while(ures_hasNext(rb) && U_SUCCESS(status)) { // iterate over items
|
||||
subString = ures_getNextResource(rb, subString, &status);
|
||||
|
||||
if(U_FAILURE(status) || (subString==NULL)) break;
|
||||
|
||||
|
@ -542,7 +569,7 @@ void RelativeDateFormat::loadDates(UErrorCode &status) {
|
|||
n++;
|
||||
}
|
||||
ures_close(subString);
|
||||
ures_close(sb);
|
||||
ures_close(rb);
|
||||
|
||||
// the fDates[] array could be sorted here, for direct access.
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "unicode/datefmt.h"
|
||||
#include "unicode/smpdtfmt.h"
|
||||
#include "unicode/brkiter.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -232,6 +233,19 @@ public:
|
|||
*/
|
||||
virtual const DateFormatSymbols* getDateFormatSymbols(void) const;
|
||||
|
||||
/* Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual */
|
||||
/**
|
||||
* Set a particular UDisplayContext value in the formatter, such as
|
||||
* UDISPCTX_CAPITALIZATION_FOR_STANDALONE. Note: For getContext, see
|
||||
* DateFormat.
|
||||
* @param value The UDisplayContext value to set.
|
||||
* @param status Input/output status. If at entry this indicates a failure
|
||||
* status, the function will do nothing; otherwise this will be
|
||||
* updated with any new status from the function.
|
||||
* @internal ICU 53
|
||||
*/
|
||||
virtual void setContext(UDisplayContext value, UErrorCode& status);
|
||||
|
||||
private:
|
||||
SimpleDateFormat *fDateTimeFormatter;
|
||||
UnicodeString fDatePattern;
|
||||
|
@ -246,8 +260,11 @@ private:
|
|||
int32_t fDatesLen; // Length of array
|
||||
URelativeString *fDates; // array of strings
|
||||
|
||||
UBool fCapitalizationForRelativeUnits[2];
|
||||
UBool fCombinedHasDateAtStart;
|
||||
UBool fCapitalizationInfoSet;
|
||||
UBool fCapitalizationOfRelativeUnitsForUIListMenu;
|
||||
UBool fCapitalizationOfRelativeUnitsForStandAlone;
|
||||
BreakIterator* fCapitalizationBrkIter;
|
||||
|
||||
/**
|
||||
* Get the string at a specific offset.
|
||||
|
@ -262,6 +279,11 @@ private:
|
|||
*/
|
||||
void loadDates(UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Set fCapitalizationOfRelativeUnitsForUIListMenu, fCapitalizationOfRelativeUnitsForStandAlone
|
||||
*/
|
||||
void initCapitalizationContextInfo(const Locale& thelocale);
|
||||
|
||||
/**
|
||||
* @return the number of days in "until-now"
|
||||
*/
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "unicode/utf16.h"
|
||||
#include "unicode/vtzone.h"
|
||||
#include "unicode/udisplaycontext.h"
|
||||
#include "unicode/brkiter.h"
|
||||
#include "olsontz.h"
|
||||
#include "patternprops.h"
|
||||
#include "fphdlimp.h"
|
||||
|
@ -236,6 +237,8 @@ SimpleDateFormat::~SimpleDateFormat()
|
|||
delete cur->nf;
|
||||
uprv_free(cur);
|
||||
}
|
||||
|
||||
delete fCapitalizationBrkIter;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -245,7 +248,8 @@ SimpleDateFormat::SimpleDateFormat(UErrorCode& status)
|
|||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
initializeBooleanAttributes();
|
||||
construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
|
||||
|
@ -261,7 +265,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
fDateOverride.setToBogus();
|
||||
fTimeOverride.setToBogus();
|
||||
|
@ -281,7 +286,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
fDateOverride.setTo(override);
|
||||
fTimeOverride.setToBogus();
|
||||
|
@ -303,7 +309,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fLocale(locale),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
|
||||
fDateOverride.setToBogus();
|
||||
|
@ -325,7 +332,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fLocale(locale),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
|
||||
fDateOverride.setTo(override);
|
||||
|
@ -350,7 +358,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fSymbols(symbolsToAdopt),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
|
||||
fDateOverride.setToBogus();
|
||||
|
@ -372,7 +381,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fSymbols(new DateFormatSymbols(symbols)),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
|
||||
fDateOverride.setToBogus();
|
||||
|
@ -395,7 +405,8 @@ SimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
|
|||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
initializeBooleanAttributes();
|
||||
construct(timeStyle, dateStyle, fLocale, status);
|
||||
|
@ -418,7 +429,8 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
|
|||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
if (U_FAILURE(status)) return;
|
||||
initializeBooleanAttributes();
|
||||
|
@ -453,7 +465,8 @@ SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
|
|||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL)
|
||||
fOverrideList(NULL),
|
||||
fCapitalizationBrkIter(NULL)
|
||||
{
|
||||
initializeBooleanAttributes();
|
||||
*this = other;
|
||||
|
@ -486,6 +499,10 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
|
|||
fTimeZoneFormat = NULL; // forces lazy instantiation with the other locale
|
||||
fLocale = other.fLocale;
|
||||
}
|
||||
|
||||
if (other.fCapitalizationBrkIter != NULL) {
|
||||
fCapitalizationBrkIter = (other.fCapitalizationBrkIter)->clone();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -504,6 +521,8 @@ UBool
|
|||
SimpleDateFormat::operator==(const Format& other) const
|
||||
{
|
||||
if (DateFormat::operator==(other)) {
|
||||
// The DateFormat::operator== check for fCapitalizationContext equality above
|
||||
// is sufficient to check equality of all derived context-related data.
|
||||
// DateFormat::operator== guarantees following cast is safe
|
||||
SimpleDateFormat* that = (SimpleDateFormat*)&other;
|
||||
return (fPattern == that->fPattern &&
|
||||
|
@ -1591,8 +1610,8 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
break;
|
||||
}
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
if (fieldNum == 0) {
|
||||
// first field, check to see whether we need to titlecase it
|
||||
// if first field, check to see whether we need to and are able to titlecase it
|
||||
if (fieldNum == 0 && u_islower(appendTo.char32At(beginOffset)) && fCapitalizationBrkIter != NULL) {
|
||||
UBool titlecase = FALSE;
|
||||
switch (capitalizationContext) {
|
||||
case UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE:
|
||||
|
@ -1610,7 +1629,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
}
|
||||
if (titlecase) {
|
||||
UnicodeString firstField(appendTo, beginOffset);
|
||||
firstField.toTitle(NULL, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
firstField.toTitle(fCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
appendTo.replaceBetween(beginOffset, appendTo.length(), firstField);
|
||||
}
|
||||
}
|
||||
|
@ -3275,6 +3294,31 @@ void SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
|
|||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
// override the DateFormat implementation in order to
|
||||
// lazily initialize fCapitalizationBrkIter
|
||||
void
|
||||
SimpleDateFormat::setContext(UDisplayContext value, UErrorCode& status)
|
||||
{
|
||||
DateFormat::setContext(value, status);
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
if (U_SUCCESS(status)) {
|
||||
if ( fCapitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
||||
value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE) ) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fCapitalizationBrkIter = BreakIterator::createSentenceInstance(fLocale, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete fCapitalizationBrkIter;
|
||||
fCapitalizationBrkIter = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
UBool
|
||||
SimpleDateFormat::isFieldUnitIgnored(UCalendarDateFields field) const {
|
||||
return isFieldUnitIgnored(fPattern, field);
|
||||
|
|
|
@ -981,11 +981,7 @@ private:
|
|||
UBool capitalizationInfoSet;
|
||||
UBool capitalizationForUIListMenu;
|
||||
UBool capitalizationForStandAlone;
|
||||
#if !UCONFIG_NO_BREAK_ITERATION
|
||||
BreakIterator* capitalizationBrkIter;
|
||||
#else
|
||||
void* capitalizationBrkIter;
|
||||
#endif
|
||||
};
|
||||
|
||||
// ---------------
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "unicode/datefmt.h"
|
||||
#include "unicode/udisplaycontext.h"
|
||||
#include "unicode/tzfmt.h" /* for UTimeZoneFormatTimeType */
|
||||
#include "unicode/brkiter.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -1108,6 +1109,19 @@ public:
|
|||
*/
|
||||
virtual const TimeZoneFormat* getTimeZoneFormat(void) const;
|
||||
|
||||
/* Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual */
|
||||
/**
|
||||
* Set a particular UDisplayContext value in the formatter, such as
|
||||
* UDISPCTX_CAPITALIZATION_FOR_STANDALONE. Note: For getContext, see
|
||||
* DateFormat.
|
||||
* @param value The UDisplayContext value to set.
|
||||
* @param status Input/output status. If at entry this indicates a failure
|
||||
* status, the function will do nothing; otherwise this will be
|
||||
* updated with any new status from the function.
|
||||
* @draft ICU 53
|
||||
*/
|
||||
virtual void setContext(UDisplayContext value, UErrorCode& status);
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
/**
|
||||
* This is for ICU internal use only. Please do not use.
|
||||
|
@ -1516,6 +1530,8 @@ private:
|
|||
NSOverride *fOverrideList;
|
||||
|
||||
UBool fHaveDefaultCentury;
|
||||
|
||||
BreakIterator* fCapitalizationBrkIter;
|
||||
};
|
||||
|
||||
inline UDate
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 2010-2013, International Business Machines Corporation and
|
||||
* Copyright (c) 2010-2014, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
*********************************************************************/
|
||||
|
||||
|
@ -294,14 +294,21 @@ static const LocNameDispContextItem ctxtItems[] = {
|
|||
{ "da", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en_US, daFor_en_US_DT },
|
||||
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en, esFor_en_T },
|
||||
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en_US, esFor_en_US_T },
|
||||
{ "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, esFor_en_US_DT },
|
||||
{ "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en_US, esFor_en_US_DT },
|
||||
|
||||
{ "da", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en, daFor_en_T },
|
||||
{ "da", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, daFor_en_US_T },
|
||||
{ "da", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, daFor_en_US_DT },
|
||||
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en, esFor_en_T },
|
||||
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, esFor_en_US_T },
|
||||
{ "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en_US, esFor_en_US_DT },
|
||||
{ "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, esFor_en_US_DT },
|
||||
|
||||
{ "da", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en, daFor_en },
|
||||
{ "da", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en_US, daFor_en_US },
|
||||
{ "da", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en_US, daFor_en_US_D },
|
||||
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en, esFor_en_T },
|
||||
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en_US, esFor_en_US_T },
|
||||
{ "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en_US, esFor_en_US_DT },
|
||||
#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
|
||||
{ NULL, (UDisplayContext)0, (UDisplayContext)0, NULL, NULL }
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue