ICU-13513 Merging trunk to branch
X-SVN-Rev: 40819
This commit is contained in:
commit
8d366b982d
@ -64,7 +64,9 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedBreakIterator)
|
||||
* Constructs a RuleBasedBreakIterator that uses the already-created
|
||||
* tables object that is passed in as a parameter.
|
||||
*/
|
||||
RuleBasedBreakIterator::RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode &status) {
|
||||
RuleBasedBreakIterator::RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode &status)
|
||||
: fSCharIter(UnicodeString())
|
||||
{
|
||||
init(status);
|
||||
fData = new RBBIDataWrapper(data, status); // status checked in constructor
|
||||
if (U_FAILURE(status)) {return;}
|
||||
@ -80,7 +82,9 @@ RuleBasedBreakIterator::RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode
|
||||
//
|
||||
RuleBasedBreakIterator::RuleBasedBreakIterator(const uint8_t *compiledRules,
|
||||
uint32_t ruleLength,
|
||||
UErrorCode &status) {
|
||||
UErrorCode &status)
|
||||
: fSCharIter(UnicodeString())
|
||||
{
|
||||
init(status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
@ -110,6 +114,7 @@ RuleBasedBreakIterator::RuleBasedBreakIterator(const uint8_t *compiledRules,
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
RuleBasedBreakIterator::RuleBasedBreakIterator(UDataMemory* udm, UErrorCode &status)
|
||||
: fSCharIter(UnicodeString())
|
||||
{
|
||||
init(status);
|
||||
fData = new RBBIDataWrapper(udm, status); // status checked in constructor
|
||||
@ -130,6 +135,7 @@ RuleBasedBreakIterator::RuleBasedBreakIterator(UDataMemory* udm, UErrorCode &sta
|
||||
RuleBasedBreakIterator::RuleBasedBreakIterator( const UnicodeString &rules,
|
||||
UParseError &parseError,
|
||||
UErrorCode &status)
|
||||
: fSCharIter(UnicodeString())
|
||||
{
|
||||
init(status);
|
||||
if (U_FAILURE(status)) {return;}
|
||||
@ -152,7 +158,9 @@ RuleBasedBreakIterator::RuleBasedBreakIterator( const UnicodeString &rules,
|
||||
// Used when creating a RuleBasedBreakIterator from a set
|
||||
// of rules.
|
||||
//-------------------------------------------------------------------------------
|
||||
RuleBasedBreakIterator::RuleBasedBreakIterator() {
|
||||
RuleBasedBreakIterator::RuleBasedBreakIterator()
|
||||
: fSCharIter(UnicodeString())
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
init(status);
|
||||
}
|
||||
@ -165,7 +173,8 @@ RuleBasedBreakIterator::RuleBasedBreakIterator() {
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
RuleBasedBreakIterator::RuleBasedBreakIterator(const RuleBasedBreakIterator& other)
|
||||
: BreakIterator(other)
|
||||
: BreakIterator(other),
|
||||
fSCharIter(UnicodeString())
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
this->init(status);
|
||||
@ -177,17 +186,13 @@ RuleBasedBreakIterator::RuleBasedBreakIterator(const RuleBasedBreakIterator& oth
|
||||
* Destructor
|
||||
*/
|
||||
RuleBasedBreakIterator::~RuleBasedBreakIterator() {
|
||||
if (fCharIter!=fSCharIter && fCharIter!=fDCharIter) {
|
||||
if (fCharIter != &fSCharIter) {
|
||||
// fCharIter was adopted from the outside.
|
||||
delete fCharIter;
|
||||
}
|
||||
fCharIter = NULL;
|
||||
delete fSCharIter;
|
||||
fSCharIter = NULL;
|
||||
delete fDCharIter;
|
||||
fDCharIter = NULL;
|
||||
|
||||
utext_close(fText);
|
||||
utext_close(&fText);
|
||||
|
||||
if (fData != NULL) {
|
||||
fData->removeReference();
|
||||
@ -224,19 +229,23 @@ RuleBasedBreakIterator::operator=(const RuleBasedBreakIterator& that) {
|
||||
}
|
||||
// TODO: clone fLanguageBreakEngines from "that"
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fText = utext_clone(fText, that.fText, FALSE, TRUE, &status);
|
||||
utext_clone(&fText, &that.fText, FALSE, TRUE, &status);
|
||||
|
||||
if (fCharIter!=fSCharIter && fCharIter!=fDCharIter) {
|
||||
if (fCharIter != &fSCharIter) {
|
||||
delete fCharIter;
|
||||
}
|
||||
fCharIter = NULL;
|
||||
fCharIter = &fSCharIter;
|
||||
|
||||
if (that.fCharIter != NULL ) {
|
||||
if (that.fCharIter != NULL && that.fCharIter != &that.fSCharIter) {
|
||||
// This is a little bit tricky - it will intially appear that
|
||||
// this->fCharIter is adopted, even if that->fCharIter was
|
||||
// not adopted. That's ok.
|
||||
fCharIter = that.fCharIter->clone();
|
||||
}
|
||||
fSCharIter = that.fSCharIter;
|
||||
if (fCharIter == NULL) {
|
||||
fCharIter = &fSCharIter;
|
||||
}
|
||||
|
||||
if (fData != NULL) {
|
||||
fData->removeReference();
|
||||
@ -269,10 +278,8 @@ RuleBasedBreakIterator::operator=(const RuleBasedBreakIterator& that) {
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void RuleBasedBreakIterator::init(UErrorCode &status) {
|
||||
fText = NULL;
|
||||
fText = UTEXT_INITIALIZER;
|
||||
fCharIter = NULL;
|
||||
fSCharIter = NULL;
|
||||
fDCharIter = NULL;
|
||||
fData = NULL;
|
||||
fPosition = 0;
|
||||
fRuleStatusIndex = 0;
|
||||
@ -292,10 +299,10 @@ void RuleBasedBreakIterator::init(UErrorCode &status) {
|
||||
return;
|
||||
}
|
||||
|
||||
fText = utext_openUChars(NULL, NULL, 0, &status);
|
||||
utext_openUChars(&fText, NULL, 0, &status);
|
||||
fDictionaryCache = new DictionaryCache(this, status);
|
||||
fBreakCache = new BreakCache(this, status);
|
||||
if (U_SUCCESS(status) && (fText == NULL || fDictionaryCache == NULL || fBreakCache == NULL)) {
|
||||
if (U_SUCCESS(status) && (fDictionaryCache == NULL || fBreakCache == NULL)) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
@ -344,7 +351,7 @@ RuleBasedBreakIterator::operator==(const BreakIterator& that) const {
|
||||
|
||||
const RuleBasedBreakIterator& that2 = (const RuleBasedBreakIterator&) that;
|
||||
|
||||
if (!utext_equals(fText, that2.fText)) {
|
||||
if (!utext_equals(&fText, &that2.fText)) {
|
||||
// The two break iterators are operating on different text,
|
||||
// or have a different iteration position.
|
||||
// Note that fText's position is always the same as the break iterator's position.
|
||||
@ -385,7 +392,7 @@ void RuleBasedBreakIterator::setText(UText *ut, UErrorCode &status) {
|
||||
}
|
||||
fBreakCache->reset();
|
||||
fDictionaryCache->reset();
|
||||
fText = utext_clone(fText, ut, FALSE, TRUE, &status);
|
||||
utext_clone(&fText, ut, FALSE, TRUE, &status);
|
||||
|
||||
// Set up a dummy CharacterIterator to be returned if anyone
|
||||
// calls getText(). With input from UText, there is no reasonable
|
||||
@ -393,27 +400,20 @@ void RuleBasedBreakIterator::setText(UText *ut, UErrorCode &status) {
|
||||
// Return one over an empty string instead - this is the closest
|
||||
// we can come to signaling a failure.
|
||||
// (GetText() is obsolete, this failure is sort of OK)
|
||||
if (fDCharIter == NULL) {
|
||||
static const UChar c = 0;
|
||||
fDCharIter = new UCharCharacterIterator(&c, 0);
|
||||
if (fDCharIter == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
fSCharIter.setText(UnicodeString());
|
||||
|
||||
if (fCharIter!=fSCharIter && fCharIter!=fDCharIter) {
|
||||
if (fCharIter != &fSCharIter) {
|
||||
// existing fCharIter was adopted from the outside. Delete it now.
|
||||
delete fCharIter;
|
||||
}
|
||||
fCharIter = fDCharIter;
|
||||
fCharIter = &fSCharIter;
|
||||
|
||||
this->first();
|
||||
}
|
||||
|
||||
|
||||
UText *RuleBasedBreakIterator::getUText(UText *fillIn, UErrorCode &status) const {
|
||||
UText *result = utext_clone(fillIn, fText, FALSE, TRUE, &status);
|
||||
UText *result = utext_clone(fillIn, &fText, FALSE, TRUE, &status);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -439,7 +439,7 @@ void
|
||||
RuleBasedBreakIterator::adoptText(CharacterIterator* newText) {
|
||||
// If we are holding a CharacterIterator adopted from a
|
||||
// previous call to this function, delete it now.
|
||||
if (fCharIter!=fSCharIter && fCharIter!=fDCharIter) {
|
||||
if (fCharIter != &fSCharIter) {
|
||||
delete fCharIter;
|
||||
}
|
||||
|
||||
@ -450,9 +450,9 @@ RuleBasedBreakIterator::adoptText(CharacterIterator* newText) {
|
||||
if (newText==NULL || newText->startIndex() != 0) {
|
||||
// startIndex !=0 wants to be an error, but there's no way to report it.
|
||||
// Make the iterator text be an empty string.
|
||||
fText = utext_openUChars(fText, NULL, 0, &status);
|
||||
utext_openUChars(&fText, NULL, 0, &status);
|
||||
} else {
|
||||
fText = utext_openCharacterIterator(fText, newText, &status);
|
||||
utext_openCharacterIterator(&fText, newText, &status);
|
||||
}
|
||||
this->first();
|
||||
}
|
||||
@ -467,23 +467,19 @@ RuleBasedBreakIterator::setText(const UnicodeString& newText) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fBreakCache->reset();
|
||||
fDictionaryCache->reset();
|
||||
fText = utext_openConstUnicodeString(fText, &newText, &status);
|
||||
utext_openConstUnicodeString(&fText, &newText, &status);
|
||||
|
||||
// Set up a character iterator on the string.
|
||||
// Needed in case someone calls getText().
|
||||
// Can not, unfortunately, do this lazily on the (probably never)
|
||||
// call to getText(), because getText is const.
|
||||
if (fSCharIter == NULL) {
|
||||
fSCharIter = new StringCharacterIterator(newText);
|
||||
} else {
|
||||
fSCharIter->setText(newText);
|
||||
}
|
||||
fSCharIter.setText(newText);
|
||||
|
||||
if (fCharIter!=fSCharIter && fCharIter!=fDCharIter) {
|
||||
if (fCharIter != &fSCharIter) {
|
||||
// old fCharIter was adopted from the outside. Delete it.
|
||||
delete fCharIter;
|
||||
}
|
||||
fCharIter = fSCharIter;
|
||||
fCharIter = &fSCharIter;
|
||||
|
||||
this->first();
|
||||
}
|
||||
@ -503,14 +499,14 @@ RuleBasedBreakIterator &RuleBasedBreakIterator::refreshInputText(UText *input, U
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return *this;
|
||||
}
|
||||
int64_t pos = utext_getNativeIndex(fText);
|
||||
int64_t pos = utext_getNativeIndex(&fText);
|
||||
// Shallow read-only clone of the new UText into the existing input UText
|
||||
fText = utext_clone(fText, input, FALSE, TRUE, &status);
|
||||
utext_clone(&fText, input, FALSE, TRUE, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return *this;
|
||||
}
|
||||
utext_setNativeIndex(fText, pos);
|
||||
if (utext_getNativeIndex(fText) != pos) {
|
||||
utext_setNativeIndex(&fText, pos);
|
||||
if (utext_getNativeIndex(&fText) != pos) {
|
||||
// Sanity check. The new input utext is supposed to have the exact same
|
||||
// contents as the old. If we can't set to the same position, it doesn't.
|
||||
// The contents underlying the old utext might be invalid at this point,
|
||||
@ -540,7 +536,7 @@ int32_t RuleBasedBreakIterator::first(void) {
|
||||
* @return The text's past-the-end offset.
|
||||
*/
|
||||
int32_t RuleBasedBreakIterator::last(void) {
|
||||
int32_t endPos = (int32_t)utext_nativeLength(fText);
|
||||
int32_t endPos = (int32_t)utext_nativeLength(&fText);
|
||||
UBool endShouldBeBoundary = isBoundary(endPos); // Has side effect of setting iterator position.
|
||||
(void)endShouldBeBoundary;
|
||||
U_ASSERT(endShouldBeBoundary);
|
||||
@ -611,8 +607,8 @@ int32_t RuleBasedBreakIterator::following(int32_t startPos) {
|
||||
|
||||
// Move requested offset to a code point start. It might be on a trail surrogate,
|
||||
// or on a trail byte if the input is UTF-8. Or it may be beyond the end of the text.
|
||||
utext_setNativeIndex(fText, startPos);
|
||||
startPos = (int32_t)utext_getNativeIndex(fText);
|
||||
utext_setNativeIndex(&fText, startPos);
|
||||
startPos = (int32_t)utext_getNativeIndex(&fText);
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fBreakCache->following(startPos, status);
|
||||
@ -626,15 +622,15 @@ int32_t RuleBasedBreakIterator::following(int32_t startPos) {
|
||||
* @return The position of the last boundary before the starting position.
|
||||
*/
|
||||
int32_t RuleBasedBreakIterator::preceding(int32_t offset) {
|
||||
if (fText == NULL || offset > utext_nativeLength(fText)) {
|
||||
if (offset > utext_nativeLength(&fText)) {
|
||||
return last();
|
||||
}
|
||||
|
||||
// Move requested offset to a code point start. It might be on a trail surrogate,
|
||||
// or on a trail byte if the input is UTF-8.
|
||||
|
||||
utext_setNativeIndex(fText, offset);
|
||||
int32_t adjustedOffset = utext_getNativeIndex(fText);
|
||||
utext_setNativeIndex(&fText, offset);
|
||||
int32_t adjustedOffset = utext_getNativeIndex(&fText);
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fBreakCache->preceding(adjustedOffset, status);
|
||||
@ -660,8 +656,8 @@ UBool RuleBasedBreakIterator::isBoundary(int32_t offset) {
|
||||
// Note that isBoundary() is always be false for offsets that are not on code point boundaries.
|
||||
// But we still need the side effect of leaving iteration at the following boundary.
|
||||
|
||||
utext_setNativeIndex(fText, offset);
|
||||
int32_t adjustedOffset = utext_getNativeIndex(fText);
|
||||
utext_setNativeIndex(&fText, offset);
|
||||
int32_t adjustedOffset = utext_getNativeIndex(&fText);
|
||||
|
||||
bool result = false;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
@ -669,7 +665,7 @@ UBool RuleBasedBreakIterator::isBoundary(int32_t offset) {
|
||||
result = (fBreakCache->current() == offset);
|
||||
}
|
||||
|
||||
if (result && adjustedOffset < offset && utext_char32At(fText, offset) == U_SENTINEL) {
|
||||
if (result && adjustedOffset < offset && utext_char32At(&fText, offset) == U_SENTINEL) {
|
||||
// Original offset is beyond the end of the text. Return FALSE, it's not a boundary,
|
||||
// but the iteration position remains set to the end of the text, which is a boundary.
|
||||
return FALSE;
|
||||
@ -789,9 +785,9 @@ int32_t RuleBasedBreakIterator::handleNext() {
|
||||
|
||||
// if we're already at the end of the text, return DONE.
|
||||
initialPosition = fPosition;
|
||||
UTEXT_SETNATIVEINDEX(fText, initialPosition);
|
||||
UTEXT_SETNATIVEINDEX(&fText, initialPosition);
|
||||
result = initialPosition;
|
||||
c = UTEXT_NEXT32(fText);
|
||||
c = UTEXT_NEXT32(&fText);
|
||||
if (c==U_SENTINEL) {
|
||||
fDone = TRUE;
|
||||
return UBRK_DONE;
|
||||
@ -854,7 +850,7 @@ int32_t RuleBasedBreakIterator::handleNext() {
|
||||
|
||||
#ifdef RBBI_DEBUG
|
||||
if (gTrace) {
|
||||
RBBIDebugPrintf(" %4ld ", utext_getNativeIndex(fText));
|
||||
RBBIDebugPrintf(" %4ld ", utext_getNativeIndex(&fText));
|
||||
if (0x20<=c && c<0x7f) {
|
||||
RBBIDebugPrintf("\"%c\" ", c);
|
||||
} else {
|
||||
@ -878,7 +874,7 @@ int32_t RuleBasedBreakIterator::handleNext() {
|
||||
if (row->fAccepting == -1) {
|
||||
// Match found, common case.
|
||||
if (mode != RBBI_START) {
|
||||
result = (int32_t)UTEXT_GETNATIVEINDEX(fText);
|
||||
result = (int32_t)UTEXT_GETNATIVEINDEX(&fText);
|
||||
}
|
||||
fRuleStatusIndex = row->fTagIdx; // Remember the break status (tag) values.
|
||||
}
|
||||
@ -896,7 +892,7 @@ int32_t RuleBasedBreakIterator::handleNext() {
|
||||
int16_t rule = row->fLookAhead;
|
||||
if (rule != 0) {
|
||||
// At the position of a '/' in a look-ahead match. Record it.
|
||||
int32_t pos = (int32_t)UTEXT_GETNATIVEINDEX(fText);
|
||||
int32_t pos = (int32_t)UTEXT_GETNATIVEINDEX(&fText);
|
||||
lookAheadMatches.setPosition(rule, pos);
|
||||
}
|
||||
|
||||
@ -912,7 +908,7 @@ int32_t RuleBasedBreakIterator::handleNext() {
|
||||
// the input position. The next iteration will be processing the
|
||||
// first real input character.
|
||||
if (mode == RBBI_RUN) {
|
||||
c = UTEXT_NEXT32(fText);
|
||||
c = UTEXT_NEXT32(&fText);
|
||||
} else {
|
||||
if (mode == RBBI_START) {
|
||||
mode = RBBI_RUN;
|
||||
@ -926,9 +922,9 @@ int32_t RuleBasedBreakIterator::handleNext() {
|
||||
// (This really indicates a defect in the break rules. They should always match
|
||||
// at least one character.)
|
||||
if (result == initialPosition) {
|
||||
utext_setNativeIndex(fText, initialPosition);
|
||||
utext_next32(fText);
|
||||
result = (int32_t)utext_getNativeIndex(fText);
|
||||
utext_setNativeIndex(&fText, initialPosition);
|
||||
utext_next32(&fText);
|
||||
result = (int32_t)utext_getNativeIndex(&fText);
|
||||
fRuleStatusIndex = 0;
|
||||
}
|
||||
|
||||
@ -963,7 +959,7 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) {
|
||||
int32_t initialPosition = 0;
|
||||
|
||||
const RBBIStateTable *stateTable = fData->fSafeRevTable;
|
||||
UTEXT_SETNATIVEINDEX(fText, fromPosition);
|
||||
UTEXT_SETNATIVEINDEX(&fText, fromPosition);
|
||||
#ifdef RBBI_DEBUG
|
||||
if (gTrace) {
|
||||
RBBIDebugPuts("Handle Previous pos char state category");
|
||||
@ -971,14 +967,14 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) {
|
||||
#endif
|
||||
|
||||
// if we're already at the start of the text, return DONE.
|
||||
if (fText == NULL || fData == NULL || UTEXT_GETNATIVEINDEX(fText)==0) {
|
||||
if (fData == NULL || UTEXT_GETNATIVEINDEX(&fText)==0) {
|
||||
return BreakIterator::DONE;
|
||||
}
|
||||
|
||||
// Set up the starting char.
|
||||
initialPosition = (int32_t)UTEXT_GETNATIVEINDEX(fText);
|
||||
initialPosition = (int32_t)UTEXT_GETNATIVEINDEX(&fText);
|
||||
result = initialPosition;
|
||||
c = UTEXT_PREVIOUS32(fText);
|
||||
c = UTEXT_PREVIOUS32(&fText);
|
||||
|
||||
// Set the initial state for the state machine
|
||||
state = START_STATE;
|
||||
@ -1026,7 +1022,7 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) {
|
||||
|
||||
#ifdef RBBI_DEBUG
|
||||
if (gTrace) {
|
||||
RBBIDebugPrintf(" %4d ", (int32_t)utext_getNativeIndex(fText));
|
||||
RBBIDebugPrintf(" %4d ", (int32_t)utext_getNativeIndex(&fText));
|
||||
if (0x20<=c && c<0x7f) {
|
||||
RBBIDebugPrintf("\"%c\" ", c);
|
||||
} else {
|
||||
@ -1047,7 +1043,7 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) {
|
||||
|
||||
if (row->fAccepting == -1) {
|
||||
// Match found, common case.
|
||||
result = (int32_t)UTEXT_GETNATIVEINDEX(fText);
|
||||
result = (int32_t)UTEXT_GETNATIVEINDEX(&fText);
|
||||
}
|
||||
|
||||
int16_t completedRule = row->fAccepting;
|
||||
@ -1055,14 +1051,14 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) {
|
||||
// Lookahead match is completed.
|
||||
int32_t lookaheadResult = lookAheadMatches.getPosition(completedRule);
|
||||
if (lookaheadResult >= 0) {
|
||||
UTEXT_SETNATIVEINDEX(fText, lookaheadResult);
|
||||
UTEXT_SETNATIVEINDEX(&fText, lookaheadResult);
|
||||
return lookaheadResult;
|
||||
}
|
||||
}
|
||||
int16_t rule = row->fLookAhead;
|
||||
if (rule != 0) {
|
||||
// At the position of a '/' in a look-ahead match. Record it.
|
||||
int32_t pos = (int32_t)UTEXT_GETNATIVEINDEX(fText);
|
||||
int32_t pos = (int32_t)UTEXT_GETNATIVEINDEX(&fText);
|
||||
lookAheadMatches.setPosition(rule, pos);
|
||||
}
|
||||
|
||||
@ -1078,7 +1074,7 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) {
|
||||
// the input position. The next iteration will be processing the
|
||||
// first real input character.
|
||||
if (mode == RBBI_RUN) {
|
||||
c = UTEXT_PREVIOUS32(fText);
|
||||
c = UTEXT_PREVIOUS32(&fText);
|
||||
} else {
|
||||
if (mode == RBBI_START) {
|
||||
mode = RBBI_RUN;
|
||||
@ -1092,9 +1088,9 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) {
|
||||
// (This really indicates a defect in the break rules. They should always match
|
||||
// at least one character.)
|
||||
if (result == initialPosition) {
|
||||
UTEXT_SETNATIVEINDEX(fText, initialPosition);
|
||||
UTEXT_PREVIOUS32(fText);
|
||||
result = (int32_t)UTEXT_GETNATIVEINDEX(fText);
|
||||
UTEXT_SETNATIVEINDEX(&fText, initialPosition);
|
||||
UTEXT_PREVIOUS32(&fText);
|
||||
result = (int32_t)UTEXT_GETNATIVEINDEX(&fText);
|
||||
}
|
||||
|
||||
#ifdef RBBI_DEBUG
|
||||
|
@ -26,14 +26,11 @@ U_NAMESPACE_BEGIN
|
||||
*/
|
||||
|
||||
RuleBasedBreakIterator::DictionaryCache::DictionaryCache(RuleBasedBreakIterator *bi, UErrorCode &status) :
|
||||
fBI(bi), fBreaks(NULL), fPositionInCache(-1),
|
||||
fBI(bi), fBreaks(status), fPositionInCache(-1),
|
||||
fStart(0), fLimit(0), fFirstRuleStatusIndex(0), fOtherRuleStatusIndex(0) {
|
||||
fBreaks = new UVector32(status);
|
||||
}
|
||||
|
||||
RuleBasedBreakIterator::DictionaryCache::~DictionaryCache() {
|
||||
delete fBreaks;
|
||||
fBreaks = NULL;
|
||||
}
|
||||
|
||||
void RuleBasedBreakIterator::DictionaryCache::reset() {
|
||||
@ -42,7 +39,7 @@ void RuleBasedBreakIterator::DictionaryCache::reset() {
|
||||
fLimit = 0;
|
||||
fFirstRuleStatusIndex = 0;
|
||||
fOtherRuleStatusIndex = 0;
|
||||
fBreaks->removeAllElements();
|
||||
fBreaks.removeAllElements();
|
||||
}
|
||||
|
||||
UBool RuleBasedBreakIterator::DictionaryCache::following(int32_t fromPos, int32_t *result, int32_t *statusIndex) {
|
||||
@ -54,13 +51,13 @@ UBool RuleBasedBreakIterator::DictionaryCache::following(int32_t fromPos, int32_
|
||||
// Sequential iteration, move from previous boundary to the following
|
||||
|
||||
int32_t r = 0;
|
||||
if (fPositionInCache >= 0 && fPositionInCache < fBreaks->size() && fBreaks->elementAti(fPositionInCache) == fromPos) {
|
||||
if (fPositionInCache >= 0 && fPositionInCache < fBreaks.size() && fBreaks.elementAti(fPositionInCache) == fromPos) {
|
||||
++fPositionInCache;
|
||||
if (fPositionInCache >= fBreaks->size()) {
|
||||
if (fPositionInCache >= fBreaks.size()) {
|
||||
fPositionInCache = -1;
|
||||
return FALSE;
|
||||
}
|
||||
r = fBreaks->elementAti(fPositionInCache);
|
||||
r = fBreaks.elementAti(fPositionInCache);
|
||||
U_ASSERT(r > fromPos);
|
||||
*result = r;
|
||||
*statusIndex = fOtherRuleStatusIndex;
|
||||
@ -69,8 +66,8 @@ UBool RuleBasedBreakIterator::DictionaryCache::following(int32_t fromPos, int32_
|
||||
|
||||
// Random indexing. Linear search for the boundary following the given position.
|
||||
|
||||
for (fPositionInCache = 0; fPositionInCache < fBreaks->size(); ++fPositionInCache) {
|
||||
r= fBreaks->elementAti(fPositionInCache);
|
||||
for (fPositionInCache = 0; fPositionInCache < fBreaks.size(); ++fPositionInCache) {
|
||||
r= fBreaks.elementAti(fPositionInCache);
|
||||
if (r > fromPos) {
|
||||
*result = r;
|
||||
*statusIndex = fOtherRuleStatusIndex;
|
||||
@ -90,16 +87,16 @@ UBool RuleBasedBreakIterator::DictionaryCache::preceding(int32_t fromPos, int32_
|
||||
}
|
||||
|
||||
if (fromPos == fLimit) {
|
||||
fPositionInCache = fBreaks->size() - 1;
|
||||
fPositionInCache = fBreaks.size() - 1;
|
||||
if (fPositionInCache >= 0) {
|
||||
U_ASSERT(fBreaks->elementAti(fPositionInCache) == fromPos);
|
||||
U_ASSERT(fBreaks.elementAti(fPositionInCache) == fromPos);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t r;
|
||||
if (fPositionInCache > 0 && fPositionInCache < fBreaks->size() && fBreaks->elementAti(fPositionInCache) == fromPos) {
|
||||
if (fPositionInCache > 0 && fPositionInCache < fBreaks.size() && fBreaks.elementAti(fPositionInCache) == fromPos) {
|
||||
--fPositionInCache;
|
||||
r = fBreaks->elementAti(fPositionInCache);
|
||||
r = fBreaks.elementAti(fPositionInCache);
|
||||
U_ASSERT(r < fromPos);
|
||||
*result = r;
|
||||
*statusIndex = ( r== fStart) ? fFirstRuleStatusIndex : fOtherRuleStatusIndex;
|
||||
@ -111,8 +108,8 @@ UBool RuleBasedBreakIterator::DictionaryCache::preceding(int32_t fromPos, int32_
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (fPositionInCache = fBreaks->size()-1; fPositionInCache >= 0; --fPositionInCache) {
|
||||
r = fBreaks->elementAti(fPositionInCache);
|
||||
for (fPositionInCache = fBreaks.size()-1; fPositionInCache >= 0; --fPositionInCache) {
|
||||
r = fBreaks.elementAti(fPositionInCache);
|
||||
if (r < fromPos) {
|
||||
*result = r;
|
||||
*statusIndex = ( r == fStart) ? fFirstRuleStatusIndex : fOtherRuleStatusIndex;
|
||||
@ -141,7 +138,7 @@ void RuleBasedBreakIterator::DictionaryCache::populateDictionary(int32_t startPo
|
||||
int32_t current;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t foundBreakCount = 0;
|
||||
UText *text = fBI->fText;
|
||||
UText *text = &fBI->fText;
|
||||
|
||||
// Loop through the text, looking for ranges of dictionary characters.
|
||||
// For each span, find the appropriate break engine, and ask it to find
|
||||
@ -168,7 +165,7 @@ void RuleBasedBreakIterator::DictionaryCache::populateDictionary(int32_t startPo
|
||||
// Ask the language object if there are any breaks. It will add them to the cache and
|
||||
// leave the text pointer on the other side of its range, ready to search for the next one.
|
||||
if (lbe != NULL) {
|
||||
foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBI->fBreakType, *fBreaks);
|
||||
foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBI->fBreakType, fBreaks);
|
||||
}
|
||||
|
||||
// Reload the loop variables for the next go-round
|
||||
@ -182,21 +179,21 @@ void RuleBasedBreakIterator::DictionaryCache::populateDictionary(int32_t startPo
|
||||
|
||||
// printf("foundBreakCount = %d\n", foundBreakCount);
|
||||
if (foundBreakCount > 0) {
|
||||
U_ASSERT(foundBreakCount == fBreaks->size());
|
||||
if (startPos < fBreaks->elementAti(0)) {
|
||||
U_ASSERT(foundBreakCount == fBreaks.size());
|
||||
if (startPos < fBreaks.elementAti(0)) {
|
||||
// The dictionary did not place a boundary at the start of the segment of text.
|
||||
// Add one now. This should not commonly happen, but it would be easy for interactions
|
||||
// of the rules for dictionary segments and the break engine implementations to
|
||||
// inadvertently cause it. Cover it here, just in case.
|
||||
fBreaks->insertElementAt(startPos, 0, status);
|
||||
fBreaks.insertElementAt(startPos, 0, status);
|
||||
}
|
||||
if (endPos > fBreaks->peeki()) {
|
||||
fBreaks->push(endPos, status);
|
||||
if (endPos > fBreaks.peeki()) {
|
||||
fBreaks.push(endPos, status);
|
||||
}
|
||||
fPositionInCache = 0;
|
||||
// Note: Dictionary matching may extend beyond the original limit.
|
||||
fStart = fBreaks->elementAti(0);
|
||||
fLimit = fBreaks->peeki();
|
||||
fStart = fBreaks.elementAti(0);
|
||||
fLimit = fBreaks.peeki();
|
||||
} else {
|
||||
// there were no language-based breaks, even though the segment contained
|
||||
// dictionary characters. Subsequent attempts to fetch boundaries from the dictionary cache
|
||||
|
@ -56,7 +56,7 @@ class RuleBasedBreakIterator::DictionaryCache: public UMemory {
|
||||
|
||||
RuleBasedBreakIterator *fBI;
|
||||
|
||||
UVector32 *fBreaks; // A vector containing the boundaries.
|
||||
UVector32 fBreaks; // A vector containing the boundaries.
|
||||
int32_t fPositionInCache; // Index in fBreaks of last boundary returned by following()
|
||||
// or preceding(). Optimizes sequential access.
|
||||
int32_t fStart; // Text position of first boundary in cache.
|
||||
|
@ -55,7 +55,7 @@ T_UConverter_toUnicode_UTF32_BE(UConverterToUnicodeArgs * args,
|
||||
uint32_t ch, i;
|
||||
|
||||
/* Restore state of current sequence */
|
||||
if (args->converter->toUnicodeStatus && myTarget < targetLimit) {
|
||||
if (args->converter->toULength > 0 && myTarget < targetLimit) {
|
||||
i = args->converter->toULength; /* restore # of bytes consumed */
|
||||
args->converter->toULength = 0;
|
||||
|
||||
@ -136,7 +136,7 @@ T_UConverter_toUnicode_UTF32_BE_OFFSET_LOGIC(UConverterToUnicodeArgs * args,
|
||||
int32_t offsetNum = 0;
|
||||
|
||||
/* Restore state of current sequence */
|
||||
if (args->converter->toUnicodeStatus && myTarget < targetLimit) {
|
||||
if (args->converter->toULength > 0 && myTarget < targetLimit) {
|
||||
i = args->converter->toULength; /* restore # of bytes consumed */
|
||||
args->converter->toULength = 0;
|
||||
|
||||
@ -517,7 +517,7 @@ T_UConverter_toUnicode_UTF32_LE(UConverterToUnicodeArgs * args,
|
||||
uint32_t ch, i;
|
||||
|
||||
/* Restore state of current sequence */
|
||||
if (args->converter->toUnicodeStatus && myTarget < targetLimit)
|
||||
if (args->converter->toULength > 0 && myTarget < targetLimit)
|
||||
{
|
||||
i = args->converter->toULength; /* restore # of bytes consumed */
|
||||
args->converter->toULength = 0;
|
||||
@ -604,7 +604,7 @@ T_UConverter_toUnicode_UTF32_LE_OFFSET_LOGIC(UConverterToUnicodeArgs * args,
|
||||
int32_t offsetNum = 0;
|
||||
|
||||
/* Restore state of current sequence */
|
||||
if (args->converter->toUnicodeStatus && myTarget < targetLimit)
|
||||
if (args->converter->toULength > 0 && myTarget < targetLimit)
|
||||
{
|
||||
i = args->converter->toULength; /* restore # of bytes consumed */
|
||||
args->converter->toULength = 0;
|
||||
|
@ -76,7 +76,7 @@ static void U_CALLCONV ucnv_toUnicode_UTF8 (UConverterToUnicodeArgs * args,
|
||||
int32_t i, inBytes;
|
||||
|
||||
/* Restore size of current sequence */
|
||||
if (cnv->toUnicodeStatus && myTarget < targetLimit)
|
||||
if (cnv->toULength > 0 && myTarget < targetLimit)
|
||||
{
|
||||
inBytes = cnv->mode; /* restore # of bytes to consume */
|
||||
i = cnv->toULength; /* restore # of bytes consumed */
|
||||
@ -194,7 +194,7 @@ static void U_CALLCONV ucnv_toUnicode_UTF8_OFFSETS_LOGIC (UConverterToUnicodeAr
|
||||
int32_t i, inBytes;
|
||||
|
||||
/* Restore size of current sequence */
|
||||
if (cnv->toUnicodeStatus && myTarget < targetLimit)
|
||||
if (cnv->toULength > 0 && myTarget < targetLimit)
|
||||
{
|
||||
inBytes = cnv->mode; /* restore # of bytes to consume */
|
||||
i = cnv->toULength; /* restore # of bytes consumed */
|
||||
@ -670,12 +670,13 @@ ucnv_UTF8FromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
|
||||
targetCapacity=(int32_t)(pFromUArgs->targetLimit-pFromUArgs->target);
|
||||
|
||||
/* get the converter state from the UTF-8 UConverter */
|
||||
c=(UChar32)utf8->toUnicodeStatus;
|
||||
if(c!=0) {
|
||||
if(utf8->toULength > 0) {
|
||||
toULength=oldToULength=utf8->toULength;
|
||||
toULimit=(int8_t)utf8->mode;
|
||||
c=(UChar32)utf8->toUnicodeStatus;
|
||||
} else {
|
||||
toULength=oldToULength=toULimit=0;
|
||||
c = 0;
|
||||
}
|
||||
|
||||
count=(int32_t)(sourceLimit-source)+oldToULength;
|
||||
|
@ -340,7 +340,11 @@ ucnv_Latin1FromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
|
||||
targetCapacity=(int32_t)(pFromUArgs->targetLimit-pFromUArgs->target);
|
||||
|
||||
/* get the converter state from the UTF-8 UConverter */
|
||||
c=(UChar32)utf8->toUnicodeStatus;
|
||||
if (utf8->toULength > 0) {
|
||||
c=(UChar32)utf8->toUnicodeStatus;
|
||||
} else {
|
||||
c = 0;
|
||||
}
|
||||
if(c!=0 && source<sourceLimit) {
|
||||
if(targetCapacity==0) {
|
||||
*pErrorCode=U_BUFFER_OVERFLOW_ERROR;
|
||||
@ -620,7 +624,7 @@ ucnv_ASCIIFromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
|
||||
|
||||
uint8_t c;
|
||||
|
||||
if(pToUArgs->converter->toUnicodeStatus!=0) {
|
||||
if(pToUArgs->converter->toULength > 0) {
|
||||
/* no handling of partial UTF-8 characters here, fall back to pivoting */
|
||||
*pErrorCode=U_USING_DEFAULT_WARNING;
|
||||
return;
|
||||
|
@ -5064,12 +5064,13 @@ ucnv_SBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
|
||||
hasSupplementary=(UBool)(cnv->sharedData->mbcs.unicodeMask&UCNV_HAS_SUPPLEMENTARY);
|
||||
|
||||
/* get the converter state from the UTF-8 UConverter */
|
||||
c=(UChar32)utf8->toUnicodeStatus;
|
||||
if(c!=0) {
|
||||
if(utf8->toULength > 0) {
|
||||
toULength=oldToULength=utf8->toULength;
|
||||
toULimit=(int8_t)utf8->mode;
|
||||
c=(UChar32)utf8->toUnicodeStatus;
|
||||
} else {
|
||||
toULength=oldToULength=toULimit=0;
|
||||
c = 0;
|
||||
}
|
||||
|
||||
// The conversion loop checks source<sourceLimit only once per 1/2/3-byte character.
|
||||
@ -5359,12 +5360,13 @@ ucnv_DBCSFromUTF8(UConverterFromUnicodeArgs *pFromUArgs,
|
||||
hasSupplementary=(UBool)(cnv->sharedData->mbcs.unicodeMask&UCNV_HAS_SUPPLEMENTARY);
|
||||
|
||||
/* get the converter state from the UTF-8 UConverter */
|
||||
c=(UChar32)utf8->toUnicodeStatus;
|
||||
if(c!=0) {
|
||||
if(utf8->toULength > 0) {
|
||||
toULength=oldToULength=utf8->toULength;
|
||||
toULimit=(int8_t)utf8->mode;
|
||||
c=(UChar32)utf8->toUnicodeStatus;
|
||||
} else {
|
||||
toULength=oldToULength=toULimit=0;
|
||||
c = 0;
|
||||
}
|
||||
|
||||
// The conversion loop checks source<sourceLimit only once per 1/2/3-byte character.
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "unicode/udata.h"
|
||||
#include "unicode/parseerr.h"
|
||||
#include "unicode/schriter.h"
|
||||
#include "unicode/uchriter.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
@ -58,28 +57,7 @@ private:
|
||||
* The UText through which this BreakIterator accesses the text
|
||||
* @internal
|
||||
*/
|
||||
UText *fText;
|
||||
|
||||
/**
|
||||
* A character iterator that refers to the same text as the UText, above.
|
||||
* Only included for compatibility with old API, which was based on CharacterIterators.
|
||||
* Value may be adopted from outside, or one of fSCharIter or fDCharIter, below.
|
||||
*/
|
||||
CharacterIterator *fCharIter;
|
||||
|
||||
/**
|
||||
* When the input text is provided by a UnicodeString, this will point to
|
||||
* a characterIterator that wraps that data. Needed only for the
|
||||
* implementation of getText(), a backwards compatibility issue.
|
||||
*/
|
||||
StringCharacterIterator *fSCharIter;
|
||||
|
||||
/**
|
||||
* When the input text is provided by a UText, this
|
||||
* dummy CharacterIterator over an empty string will
|
||||
* be returned from getText()
|
||||
*/
|
||||
UCharCharacterIterator *fDCharIter;
|
||||
UText fText;
|
||||
|
||||
/**
|
||||
* The rule data for this BreakIterator instance
|
||||
@ -105,24 +83,11 @@ private:
|
||||
*/
|
||||
int32_t fRuleStatusIndex;
|
||||
|
||||
/**
|
||||
* True when iteration has run off the end, and iterator functions should return UBRK_DONE.
|
||||
*/
|
||||
UBool fDone;
|
||||
|
||||
/**
|
||||
* Cache of previously determined boundary positions.
|
||||
*/
|
||||
public: // TODO: debug, return to private.
|
||||
class BreakCache;
|
||||
BreakCache *fBreakCache;
|
||||
private:
|
||||
/**
|
||||
* Counter for the number of characters encountered with the "dictionary"
|
||||
* flag set.
|
||||
* @internal
|
||||
*/
|
||||
uint32_t fDictionaryCharCount;
|
||||
|
||||
/**
|
||||
* Cache of boundary positions within a region of text that has been
|
||||
@ -156,6 +121,32 @@ private:
|
||||
*/
|
||||
int32_t fBreakType;
|
||||
|
||||
/**
|
||||
* Counter for the number of characters encountered with the "dictionary"
|
||||
* flag set.
|
||||
* @internal
|
||||
*/
|
||||
uint32_t fDictionaryCharCount;
|
||||
|
||||
/**
|
||||
* A character iterator that refers to the same text as the UText, above.
|
||||
* Only included for compatibility with old API, which was based on CharacterIterators.
|
||||
* Value may be adopted from outside, or one of fSCharIter or fDCharIter, below.
|
||||
*/
|
||||
CharacterIterator *fCharIter;
|
||||
|
||||
/**
|
||||
* When the input text is provided by a UnicodeString, this will point to
|
||||
* a characterIterator that wraps that data. Needed only for the
|
||||
* implementation of getText(), a backwards compatibility issue.
|
||||
*/
|
||||
StringCharacterIterator fSCharIter;
|
||||
|
||||
/**
|
||||
* True when iteration has run off the end, and iterator functions should return UBRK_DONE.
|
||||
*/
|
||||
UBool fDone;
|
||||
|
||||
//=======================================================================
|
||||
// constructors
|
||||
//=======================================================================
|
||||
|
@ -344,7 +344,6 @@ metaZones:table(nofallback){
|
||||
SH{"Atlantic/St_Helena"}
|
||||
SL{"Africa/Freetown"}
|
||||
SN{"Africa/Dakar"}
|
||||
ST{"Africa/Sao_Tome"}
|
||||
TG{"Africa/Lome"}
|
||||
}
|
||||
Galapagos{
|
||||
@ -1030,6 +1029,13 @@ metaZones:table(nofallback){
|
||||
"Africa:Sao_Tome"{
|
||||
{
|
||||
"GMT",
|
||||
"1970-01-01 00:00",
|
||||
"2018-01-01 01:00",
|
||||
}
|
||||
{
|
||||
"Africa_Western",
|
||||
"2018-01-01 01:00",
|
||||
"9999-12-31 23:59",
|
||||
}
|
||||
}
|
||||
"Africa:Tripoli"{
|
||||
|
@ -316,7 +316,6 @@ windowsZones:table(nofallback){
|
||||
SH{"Atlantic/St_Helena"}
|
||||
SL{"Africa/Freetown"}
|
||||
SN{"Africa/Dakar"}
|
||||
ST{"Africa/Sao_Tome"}
|
||||
TG{"Africa/Lome"}
|
||||
}
|
||||
"Haiti Standard Time"{
|
||||
@ -744,6 +743,7 @@ windowsZones:table(nofallback){
|
||||
GQ{"Africa/Malabo"}
|
||||
NE{"Africa/Niamey"}
|
||||
NG{"Africa/Lagos"}
|
||||
ST{"Africa/Sao_Tome"}
|
||||
TD{"Africa/Ndjamena"}
|
||||
TN{"Africa/Tunis"}
|
||||
ZZ{"Etc/GMT-1"}
|
||||
|
@ -3,9 +3,9 @@
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
//---------------------------------------------------------
|
||||
// Build tool: tz2icu
|
||||
// Build date: Tue Oct 24 17:35:27 2017
|
||||
// Build date: Tue Jan 23 20:51:55 2018
|
||||
// tz database: ftp://ftp.iana.org/tz/
|
||||
// tz version: 2017c
|
||||
// tz version: 2018c
|
||||
// ICU version: 60.1
|
||||
//---------------------------------------------------------
|
||||
// >> !!! >> THIS IS A MACHINE-GENERATED FILE << !!! <<
|
||||
@ -13,7 +13,7 @@
|
||||
//---------------------------------------------------------
|
||||
|
||||
zoneinfo64:table(nofallback) {
|
||||
TZVersion { "2017c" }
|
||||
TZVersion { "2018c" }
|
||||
Zones:array {
|
||||
/* ACT */ :int { 354 } //Z#0
|
||||
/* AET */ :int { 366 } //Z#1
|
||||
@ -24,7 +24,7 @@ zoneinfo64:table(nofallback) {
|
||||
trans:intvector { -1830383032 }
|
||||
typeOffsets:intvector { -968, 0, 0, 0 }
|
||||
typeMap:bin { "01" }
|
||||
links:intvector { 5, 11, 13, 21, 22, 27, 38, 51, 52, 54, 55, 346 }
|
||||
links:intvector { 5, 11, 13, 21, 22, 27, 38, 51, 52, 55, 346 }
|
||||
} //Z#5
|
||||
/* Africa/Accra */ :table {
|
||||
trans:intvector { -1640995148, -1556841600, -1546388400, -1525305600, -1514852400, -1493769600, -1483316400, -1462233600, -1451780400, -1430611200, -1420158000, -1399075200, -1388622000, -1367539200, -1357086000, -1336003200, -1325550000, -1304380800, -1293927600, -1272844800, -1262391600, -1241308800, -1230855600, -1209772800, -1199319600, -1178150400, -1167697200, -1146614400, -1136161200, -1115078400, -1104625200, -1083542400, -1073089200, -1051920000, -1041466800, -1020384000, -1009930800, -988848000, -978394800, -957312000, -946858800, -925689600, -915236400, -894153600, -883700400, -862617600, -852164400 }
|
||||
@ -154,7 +154,12 @@ zoneinfo64:table(nofallback) {
|
||||
/* Africa/Nouakchott */ :int { 5 } //Z#51
|
||||
/* Africa/Ouagadougou */ :int { 5 } //Z#52
|
||||
/* Africa/Porto-Novo */ :int { 36 } //Z#53
|
||||
/* Africa/Sao_Tome */ :int { 5 } //Z#54
|
||||
/* Africa/Sao_Tome */ :table {
|
||||
transPre32:intvector { -1, 1581055280 }
|
||||
trans:intvector { -1830381795, 1514768400 }
|
||||
typeOffsets:intvector { 1616, 0, -2205, 0, 0, 0, 3600, 0 }
|
||||
typeMap:bin { "010203" }
|
||||
} //Z#54
|
||||
/* Africa/Timbuktu */ :int { 5 } //Z#55
|
||||
/* Africa/Tripoli */ :table {
|
||||
trans:intvector { -1577926364, -574902000, -568087200, -512175600, -504928800, -449888400, -441856800, -347158800, 378684000, 386463600, 402271200, 417999600, 433807200, 449622000, 465429600, 481590000, 496965600, 512953200, 528674400, 544230000, 560037600, 575852400, 591660000, 607388400, 623196000, 641775600, 844034400, 860108400, 875916000, 1352505600, 1364515200, 1382659200 }
|
||||
@ -358,8 +363,8 @@ zoneinfo64:table(nofallback) {
|
||||
finalYear:int { 2008 }
|
||||
} //Z#91
|
||||
/* America/Campo_Grande */ :table {
|
||||
trans:intvector { -1767212492, -1206954000, -1191358800, -1175371200, -1159822800, -633816000, -622065600, -602280000, -591829200, -570744000, -560206800, -539121600, -531349200, -191361600, -184194000, -155160000, -150066000, -128894400, -121122000, -99950400, -89586000, -68414400, -57963600, 499752000, 511239600, 530596800, 540270000, 562132800, 571201200, 592977600, 602046000, 624427200, 634705200, 656481600, 666759600, 687931200, 697604400, 719985600, 728449200, 750830400, 761713200, 782280000, 793162800, 813729600, 824007600, 844574400, 856062000, 876110400, 888721200, 908078400, 919566000, 938923200, 951620400, 970977600, 982465200, 1003032000, 1013914800, 1036296000, 1045364400, 1066536000, 1076814000, 1099368000, 1108868400, 1129435200, 1140318000, 1162699200, 1172372400, 1192334400, 1203217200, 1224388800, 1234666800, 1255838400, 1266721200, 1287288000, 1298170800, 1318737600, 1330225200, 1350792000, 1361070000, 1382241600, 1392519600, 1413691200, 1424574000, 1445140800, 1456023600, 1476590400, 1487473200, 1508040000, 1518922800, 1540094400, 1550372400, 1571544000, 1581822000, 1602993600, 1613876400, 1634443200, 1645326000, 1665892800, 1677380400, 1697342400, 1708225200, 1729396800, 1739674800, 1760846400, 1771729200, 1792296000, 1803178800, 1823745600, 1834628400, 1855195200, 1866078000, 1887249600, 1897527600, 1918699200, 1928977200, 1950148800, 1960426800, 1981598400, 1992481200, 2013048000, 2024535600, 2044497600, 2055380400, 2076552000, 2086830000, 2108001600, 2118884400, 2139451200 }
|
||||
transPost32:intvector { 0, -2144633296, 0, -2124066496 }
|
||||
trans:intvector { -1767212492, -1206954000, -1191358800, -1175371200, -1159822800, -633816000, -622065600, -602280000, -591829200, -570744000, -560206800, -539121600, -531349200, -191361600, -184194000, -155160000, -150066000, -128894400, -121122000, -99950400, -89586000, -68414400, -57963600, 499752000, 511239600, 530596800, 540270000, 562132800, 571201200, 592977600, 602046000, 624427200, 634705200, 656481600, 666759600, 687931200, 697604400, 719985600, 728449200, 750830400, 761713200, 782280000, 793162800, 813729600, 824007600, 844574400, 856062000, 876110400, 888721200, 908078400, 919566000, 938923200, 951620400, 970977600, 982465200, 1003032000, 1013914800, 1036296000, 1045364400, 1066536000, 1076814000, 1099368000, 1108868400, 1129435200, 1140318000, 1162699200, 1172372400, 1192334400, 1203217200, 1224388800, 1234666800, 1255838400, 1266721200, 1287288000, 1298170800, 1318737600, 1330225200, 1350792000, 1361070000, 1382241600, 1392519600, 1413691200, 1424574000, 1445140800, 1456023600, 1476590400, 1487473200, 1508040000, 1518922800, 1541304000, 1550372400, 1572753600, 1581822000, 1604203200, 1613876400, 1636257600, 1645326000, 1667707200, 1677380400, 1699156800, 1708225200, 1730606400, 1739674800, 1762056000, 1771729200, 1793505600, 1803178800, 1825560000, 1834628400, 1857009600, 1866078000, 1888459200, 1897527600, 1919908800, 1928977200, 1951358400, 1960426800, 1983412800, 1992481200, 2014862400, 2024535600, 2046312000, 2055380400, 2077761600, 2086830000, 2109211200, 2118884400, 2140660800 }
|
||||
transPost32:intvector { 0, -2144633296, 0, -2122252096 }
|
||||
typeOffsets:intvector { -13108, 0, -14400, 0, -14400, 3600 }
|
||||
typeMap:bin { "01020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102" }
|
||||
finalRule { "Brazil" }
|
||||
@ -416,8 +421,8 @@ zoneinfo64:table(nofallback) {
|
||||
typeMap:bin { "020102" }
|
||||
} //Z#103
|
||||
/* America/Cuiaba */ :table {
|
||||
trans:intvector { -1767212140, -1206954000, -1191358800, -1175371200, -1159822800, -633816000, -622065600, -602280000, -591829200, -570744000, -560206800, -539121600, -531349200, -191361600, -184194000, -155160000, -150066000, -128894400, -121122000, -99950400, -89586000, -68414400, -57963600, 499752000, 511239600, 530596800, 540270000, 562132800, 571201200, 592977600, 602046000, 624427200, 634705200, 656481600, 666759600, 687931200, 697604400, 719985600, 728449200, 750830400, 761713200, 782280000, 793162800, 813729600, 824007600, 844574400, 856062000, 876110400, 888721200, 908078400, 919566000, 938923200, 951620400, 970977600, 982465200, 1003032000, 1013914800, 1036296000, 1045364400, 1099368000, 1108868400, 1129435200, 1140318000, 1162699200, 1172372400, 1192334400, 1203217200, 1224388800, 1234666800, 1255838400, 1266721200, 1287288000, 1298170800, 1318737600, 1330225200, 1350792000, 1361070000, 1382241600, 1392519600, 1413691200, 1424574000, 1445140800, 1456023600, 1476590400, 1487473200, 1508040000, 1518922800, 1540094400, 1550372400, 1571544000, 1581822000, 1602993600, 1613876400, 1634443200, 1645326000, 1665892800, 1677380400, 1697342400, 1708225200, 1729396800, 1739674800, 1760846400, 1771729200, 1792296000, 1803178800, 1823745600, 1834628400, 1855195200, 1866078000, 1887249600, 1897527600, 1918699200, 1928977200, 1950148800, 1960426800, 1981598400, 1992481200, 2013048000, 2024535600, 2044497600, 2055380400, 2076552000, 2086830000, 2108001600, 2118884400, 2139451200 }
|
||||
transPost32:intvector { 0, -2144633296, 0, -2124066496 }
|
||||
trans:intvector { -1767212140, -1206954000, -1191358800, -1175371200, -1159822800, -633816000, -622065600, -602280000, -591829200, -570744000, -560206800, -539121600, -531349200, -191361600, -184194000, -155160000, -150066000, -128894400, -121122000, -99950400, -89586000, -68414400, -57963600, 499752000, 511239600, 530596800, 540270000, 562132800, 571201200, 592977600, 602046000, 624427200, 634705200, 656481600, 666759600, 687931200, 697604400, 719985600, 728449200, 750830400, 761713200, 782280000, 793162800, 813729600, 824007600, 844574400, 856062000, 876110400, 888721200, 908078400, 919566000, 938923200, 951620400, 970977600, 982465200, 1003032000, 1013914800, 1036296000, 1045364400, 1099368000, 1108868400, 1129435200, 1140318000, 1162699200, 1172372400, 1192334400, 1203217200, 1224388800, 1234666800, 1255838400, 1266721200, 1287288000, 1298170800, 1318737600, 1330225200, 1350792000, 1361070000, 1382241600, 1392519600, 1413691200, 1424574000, 1445140800, 1456023600, 1476590400, 1487473200, 1508040000, 1518922800, 1541304000, 1550372400, 1572753600, 1581822000, 1604203200, 1613876400, 1636257600, 1645326000, 1667707200, 1677380400, 1699156800, 1708225200, 1730606400, 1739674800, 1762056000, 1771729200, 1793505600, 1803178800, 1825560000, 1834628400, 1857009600, 1866078000, 1888459200, 1897527600, 1919908800, 1928977200, 1951358400, 1960426800, 1983412800, 1992481200, 2014862400, 2024535600, 2046312000, 2055380400, 2077761600, 2086830000, 2109211200, 2118884400, 2140660800 }
|
||||
transPost32:intvector { 0, -2144633296, 0, -2122252096 }
|
||||
typeOffsets:intvector { -13460, 0, -14400, 0, -14400, 3600 }
|
||||
typeMap:bin { "0102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102" }
|
||||
finalRule { "Brazil" }
|
||||
@ -1040,8 +1045,8 @@ zoneinfo64:table(nofallback) {
|
||||
typeMap:bin { "0401030102010201020102010201050105" }
|
||||
} //Z#201
|
||||
/* America/Sao_Paulo */ :table {
|
||||
trans:intvector { -1767214412, -1206957600, -1191362400, -1175374800, -1159826400, -633819600, -622069200, -602283600, -591832800, -570747600, -560210400, -539125200, -531352800, -195426000, -184197600, -155163600, -150069600, -128898000, -121125600, -99954000, -89589600, -68418000, -57967200, 499748400, 511236000, 530593200, 540266400, 562129200, 571197600, 592974000, 602042400, 624423600, 634701600, 656478000, 666756000, 687927600, 697600800, 719982000, 728445600, 750826800, 761709600, 782276400, 793159200, 813726000, 824004000, 844570800, 856058400, 876106800, 888717600, 908074800, 919562400, 938919600, 951616800, 970974000, 982461600, 1003028400, 1013911200, 1036292400, 1045360800, 1066532400, 1076810400, 1099364400, 1108864800, 1129431600, 1140314400, 1162695600, 1172368800, 1192330800, 1203213600, 1224385200, 1234663200, 1255834800, 1266717600, 1287284400, 1298167200, 1318734000, 1330221600, 1350788400, 1361066400, 1382238000, 1392516000, 1413687600, 1424570400, 1445137200, 1456020000, 1476586800, 1487469600, 1508036400, 1518919200, 1540090800, 1550368800, 1571540400, 1581818400, 1602990000, 1613872800, 1634439600, 1645322400, 1665889200, 1677376800, 1697338800, 1708221600, 1729393200, 1739671200, 1760842800, 1771725600, 1792292400, 1803175200, 1823742000, 1834624800, 1855191600, 1866074400, 1887246000, 1897524000, 1918695600, 1928973600, 1950145200, 1960423200, 1981594800, 1992477600, 2013044400, 2024532000, 2044494000, 2055376800, 2076548400, 2086826400, 2107998000, 2118880800, 2139447600 }
|
||||
transPost32:intvector { 0, -2144636896, 0, -2124070096 }
|
||||
trans:intvector { -1767214412, -1206957600, -1191362400, -1175374800, -1159826400, -633819600, -622069200, -602283600, -591832800, -570747600, -560210400, -539125200, -531352800, -195426000, -184197600, -155163600, -150069600, -128898000, -121125600, -99954000, -89589600, -68418000, -57967200, 499748400, 511236000, 530593200, 540266400, 562129200, 571197600, 592974000, 602042400, 624423600, 634701600, 656478000, 666756000, 687927600, 697600800, 719982000, 728445600, 750826800, 761709600, 782276400, 793159200, 813726000, 824004000, 844570800, 856058400, 876106800, 888717600, 908074800, 919562400, 938919600, 951616800, 970974000, 982461600, 1003028400, 1013911200, 1036292400, 1045360800, 1066532400, 1076810400, 1099364400, 1108864800, 1129431600, 1140314400, 1162695600, 1172368800, 1192330800, 1203213600, 1224385200, 1234663200, 1255834800, 1266717600, 1287284400, 1298167200, 1318734000, 1330221600, 1350788400, 1361066400, 1382238000, 1392516000, 1413687600, 1424570400, 1445137200, 1456020000, 1476586800, 1487469600, 1508036400, 1518919200, 1541300400, 1550368800, 1572750000, 1581818400, 1604199600, 1613872800, 1636254000, 1645322400, 1667703600, 1677376800, 1699153200, 1708221600, 1730602800, 1739671200, 1762052400, 1771725600, 1793502000, 1803175200, 1825556400, 1834624800, 1857006000, 1866074400, 1888455600, 1897524000, 1919905200, 1928973600, 1951354800, 1960423200, 1983409200, 1992477600, 2014858800, 2024532000, 2046308400, 2055376800, 2077758000, 2086826400, 2109207600, 2118880800, 2140657200 }
|
||||
transPost32:intvector { 0, -2144636896, 0, -2122255696 }
|
||||
typeOffsets:intvector { -11188, 0, -10800, 0, -10800, 3600 }
|
||||
typeMap:bin { "01020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102" }
|
||||
finalRule { "Brazil" }
|
||||
@ -1645,7 +1650,7 @@ zoneinfo64:table(nofallback) {
|
||||
} //Z#322
|
||||
/* Asia/Tokyo */ :table {
|
||||
transPre32:intvector { -1, 1707254896 }
|
||||
trans:intvector { -683794800, -672393600, -654764400, -640944000, -620290800, -609494400, -588841200, -578044800 }
|
||||
trans:intvector { -683802000, -672314400, -654771600, -640864800, -620298000, -609415200, -588848400, -577965600 }
|
||||
typeOffsets:intvector { 33539, 0, 32400, 0, 32400, 3600 }
|
||||
typeMap:bin { "010201020102010201" }
|
||||
links:intvector { 323, 527, 529 }
|
||||
@ -3083,7 +3088,7 @@ zoneinfo64:table(nofallback) {
|
||||
9, 1, -1, 7200, 1, 3, 1, -1, 7200, 1, 3600
|
||||
} //_#3
|
||||
Brazil:intvector {
|
||||
9, 15, -1, 0, 0, 1, 15, -1, 0, 0, 3600
|
||||
10, 1, -1, 0, 0, 1, 15, -1, 0, 0, 3600
|
||||
} //_#4
|
||||
C-Eur:intvector {
|
||||
2, -31, -1, 7200, 1, 9, -31, -1, 7200, 1, 3600
|
||||
|
@ -233,7 +233,7 @@ void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormat
|
||||
for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
|
||||
UnicodeString simpleFormat = getWithPlural(simpleFormats, i, status);
|
||||
if (U_FAILURE(status)) { return; }
|
||||
SimpleFormatter compiledFormatter(simpleFormat, 1, 1, status);
|
||||
SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status);
|
||||
if (U_FAILURE(status)) { return; }
|
||||
output[i] = SimpleModifier(compiledFormatter, field, false);
|
||||
}
|
||||
@ -249,7 +249,7 @@ void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFor
|
||||
UnicodeString compoundFormat;
|
||||
trailCompiled.format(leadFormat, compoundFormat, status);
|
||||
if (U_FAILURE(status)) { return; }
|
||||
SimpleFormatter compoundCompiled(compoundFormat, 1, 1, status);
|
||||
SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status);
|
||||
if (U_FAILURE(status)) { return; }
|
||||
output[i] = SimpleModifier(compoundCompiled, field, false);
|
||||
}
|
||||
|
@ -74,19 +74,29 @@ bool ConstantAffixModifier::isStrong() const {
|
||||
|
||||
SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong)
|
||||
: fCompiledPattern(simpleFormatter.compiledPattern), fField(field), fStrong(strong) {
|
||||
U_ASSERT(1 ==
|
||||
SimpleFormatter::getArgumentLimit(fCompiledPattern.getBuffer(), fCompiledPattern.length()));
|
||||
if (fCompiledPattern.charAt(1) != 0) {
|
||||
int32_t argLimit = SimpleFormatter::getArgumentLimit(
|
||||
fCompiledPattern.getBuffer(), fCompiledPattern.length());
|
||||
if (argLimit == 0) {
|
||||
// No arguments in compiled pattern
|
||||
fPrefixLength = fCompiledPattern.charAt(1) - ARG_NUM_LIMIT;
|
||||
fSuffixOffset = 3 + fPrefixLength;
|
||||
} else {
|
||||
fPrefixLength = 0;
|
||||
fSuffixOffset = 2;
|
||||
}
|
||||
if (3 + fPrefixLength < fCompiledPattern.length()) {
|
||||
fSuffixLength = fCompiledPattern.charAt(fSuffixOffset) - ARG_NUM_LIMIT;
|
||||
} else {
|
||||
U_ASSERT(2 + fPrefixLength == fCompiledPattern.length());
|
||||
// Set suffixOffset = -1 to indicate no arguments in compiled pattern.
|
||||
fSuffixOffset = -1;
|
||||
fSuffixLength = 0;
|
||||
} else {
|
||||
U_ASSERT(argLimit == 1);
|
||||
if (fCompiledPattern.charAt(1) != 0) {
|
||||
fPrefixLength = fCompiledPattern.charAt(1) - ARG_NUM_LIMIT;
|
||||
fSuffixOffset = 3 + fPrefixLength;
|
||||
} else {
|
||||
fPrefixLength = 0;
|
||||
fSuffixOffset = 2;
|
||||
}
|
||||
if (3 + fPrefixLength < fCompiledPattern.length()) {
|
||||
fSuffixLength = fCompiledPattern.charAt(fSuffixOffset) - ARG_NUM_LIMIT;
|
||||
} else {
|
||||
fSuffixLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,19 +133,24 @@ bool SimpleModifier::isStrong() const {
|
||||
int32_t
|
||||
SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex,
|
||||
Field field, UErrorCode &status) const {
|
||||
if (fPrefixLength > 0) {
|
||||
result.insert(startIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status);
|
||||
if (fSuffixOffset == -1) {
|
||||
// There is no argument for the inner number; overwrite the entire segment with our string.
|
||||
return result.splice(startIndex, endIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status);
|
||||
} else {
|
||||
if (fPrefixLength > 0) {
|
||||
result.insert(startIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status);
|
||||
}
|
||||
if (fSuffixLength > 0) {
|
||||
result.insert(
|
||||
endIndex + fPrefixLength,
|
||||
fCompiledPattern,
|
||||
1 + fSuffixOffset,
|
||||
1 + fSuffixOffset + fSuffixLength,
|
||||
field,
|
||||
status);
|
||||
}
|
||||
return fPrefixLength + fSuffixLength;
|
||||
}
|
||||
if (fSuffixLength > 0) {
|
||||
result.insert(
|
||||
endIndex + fPrefixLength,
|
||||
fCompiledPattern,
|
||||
1 + fSuffixOffset,
|
||||
1 + fSuffixOffset + fSuffixLength,
|
||||
field,
|
||||
status);
|
||||
}
|
||||
return fPrefixLength + fSuffixLength;
|
||||
}
|
||||
|
||||
int32_t ConstantMultiFieldModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
|
||||
|
@ -191,6 +191,30 @@ NumberStringBuilder::insert(int32_t index, const UnicodeString &unistr, int32_t
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t
|
||||
NumberStringBuilder::splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
|
||||
int32_t startOther, int32_t endOther, Field field, UErrorCode& status) {
|
||||
int32_t thisLength = endThis - startThis;
|
||||
int32_t otherLength = endOther - startOther;
|
||||
int32_t count = otherLength - thisLength;
|
||||
int32_t position;
|
||||
if (count > 0) {
|
||||
// Overall, chars need to be added.
|
||||
position = prepareForInsert(startThis, count, status);
|
||||
} else {
|
||||
// Overall, chars need to be removed or kept the same.
|
||||
position = remove(startThis, -count);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
return count;
|
||||
}
|
||||
for (int32_t i = 0; i < otherLength; i++) {
|
||||
getCharPtr()[position + i] = unistr.charAt(startOther + i);
|
||||
getFieldPtr()[position + i] = field;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t NumberStringBuilder::append(const NumberStringBuilder &other, UErrorCode &status) {
|
||||
return insert(fLength, other, status);
|
||||
}
|
||||
@ -296,6 +320,19 @@ int32_t NumberStringBuilder::prepareForInsertHelper(int32_t index, int32_t count
|
||||
return fZero + index;
|
||||
}
|
||||
|
||||
int32_t NumberStringBuilder::remove(int32_t index, int32_t count) {
|
||||
// TODO: Reset the heap here? (If the string after removal can fit on stack?)
|
||||
int32_t position = index + fZero;
|
||||
uprv_memmove2(getCharPtr() + position,
|
||||
getCharPtr() + position + count,
|
||||
sizeof(char16_t) * (fLength - index - count));
|
||||
uprv_memmove2(getFieldPtr() + position,
|
||||
getFieldPtr() + position + count,
|
||||
sizeof(Field) * (fLength - index - count));
|
||||
fLength -= count;
|
||||
return position;
|
||||
}
|
||||
|
||||
UnicodeString NumberStringBuilder::toUnicodeString() const {
|
||||
return UnicodeString(getCharPtr() + fZero, fLength);
|
||||
}
|
||||
|
@ -77,6 +77,9 @@ class U_I18N_API NumberStringBuilder : public UMemory {
|
||||
int32_t insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, Field field,
|
||||
UErrorCode &status);
|
||||
|
||||
int32_t splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
|
||||
int32_t startOther, int32_t endOther, Field field, UErrorCode& status);
|
||||
|
||||
int32_t append(const NumberStringBuilder &other, UErrorCode &status);
|
||||
|
||||
int32_t insert(int32_t index, const NumberStringBuilder &other, UErrorCode &status);
|
||||
@ -123,6 +126,8 @@ class U_I18N_API NumberStringBuilder : public UMemory {
|
||||
int32_t prepareForInsert(int32_t index, int32_t count, UErrorCode &status);
|
||||
|
||||
int32_t prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status);
|
||||
|
||||
int32_t remove(int32_t index, int32_t count);
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
@ -23,6 +23,11 @@
|
||||
|
||||
static UFILE *out;
|
||||
|
||||
using icu::CharacterIterator;
|
||||
using icu::StringCharacterIterator;
|
||||
using icu::UCharCharacterIterator;
|
||||
using icu::UnicodeString;
|
||||
|
||||
void printUnicodeString(const UnicodeString &s)
|
||||
{
|
||||
u_fprintf(out, "%S", &s);
|
||||
|
@ -733,6 +733,7 @@ ConversionTest::TestUTF8ToUTF8Overflow() {
|
||||
UChar *pivotSource = buffer16;
|
||||
UChar *pivotTarget = buffer16;
|
||||
const UChar *pivotLimit = buffer16 + UPRV_LENGTHOF(buffer16);
|
||||
int32_t length;
|
||||
|
||||
// Convert with insufficient target capacity.
|
||||
result[2] = 5;
|
||||
@ -741,7 +742,7 @@ ConversionTest::TestUTF8ToUTF8Overflow() {
|
||||
buffer16, &pivotSource, &pivotTarget, pivotLimit,
|
||||
FALSE, FALSE, errorCode);
|
||||
assertEquals("overflow", U_BUFFER_OVERFLOW_ERROR, errorCode.reset());
|
||||
int32_t length = (int32_t)(target - result);
|
||||
length = (int32_t)(target - result);
|
||||
assertEquals("number of bytes written", 2, length);
|
||||
assertEquals("next byte not clobbered", 5, result[2]);
|
||||
|
||||
@ -790,6 +791,52 @@ ConversionTest::TestUTF8ToUTF8Overflow() {
|
||||
if (length == 5) {
|
||||
assertTrue("text2 result same as input", memcmp(text2, result, length) == 0);
|
||||
}
|
||||
|
||||
ucnv_reset(cnv1.getAlias());
|
||||
ucnv_reset(cnv2.getAlias());
|
||||
memset(result, 0, sizeof(result));
|
||||
static const char *illFormed = "\xf1\x91\x93\x96\x91\x94"; // U+514D6 + two more trail bytes
|
||||
source = illFormed;
|
||||
sourceLimit = illFormed + strlen(illFormed);
|
||||
target = result;
|
||||
pivotSource = pivotTarget = buffer16;
|
||||
|
||||
ucnv_setToUCallBack(cnv1.getAlias(), UCNV_TO_U_CALLBACK_STOP, nullptr, nullptr, nullptr, errorCode);
|
||||
|
||||
// Convert only two bytes and flush (but expect failure).
|
||||
char errorBytes[10];
|
||||
int8_t errorLength;
|
||||
result[0] = 5;
|
||||
ucnv_convertEx(cnv2.getAlias(), cnv1.getAlias(),
|
||||
&target, targetLimit, &source, source + 2,
|
||||
buffer16, &pivotSource, &pivotTarget, pivotLimit,
|
||||
FALSE, TRUE, errorCode);
|
||||
assertEquals("illFormed truncated", U_TRUNCATED_CHAR_FOUND, errorCode.reset());
|
||||
length = (int32_t)(target - result);
|
||||
assertEquals("illFormed number of bytes written", 0, length);
|
||||
errorLength = UPRV_LENGTHOF(errorBytes);
|
||||
ucnv_getInvalidChars(cnv1.getAlias(), errorBytes, &errorLength, errorCode);
|
||||
assertEquals("illFormed truncated errorLength", 2, (int32_t)errorLength);
|
||||
if (errorLength == 2) {
|
||||
assertEquals("illFormed truncated errorBytes", 0xf191,
|
||||
((int32_t)(uint8_t)errorBytes[0] << 8) | (uint8_t)errorBytes[1]);
|
||||
}
|
||||
|
||||
// Continue conversion starting with a trail byte.
|
||||
ucnv_convertEx(cnv2.getAlias(), cnv1.getAlias(),
|
||||
&target, targetLimit, &source, sourceLimit,
|
||||
buffer16, &pivotSource, &pivotTarget, pivotLimit,
|
||||
FALSE, TRUE, errorCode);
|
||||
|
||||
assertEquals("illFormed trail byte", U_ILLEGAL_CHAR_FOUND, errorCode.reset());
|
||||
length = (int32_t)(target - result);
|
||||
assertEquals("illFormed trail byte number of bytes written", 0, length);
|
||||
errorLength = UPRV_LENGTHOF(errorBytes);
|
||||
ucnv_getInvalidChars(cnv1.getAlias(), errorBytes, &errorLength, errorCode);
|
||||
assertEquals("illFormed trail byte errorLength", 1, (int32_t)errorLength);
|
||||
if (errorLength == 1) {
|
||||
assertEquals("illFormed trail byte errorBytes", 0x93, (int32_t)(uint8_t)errorBytes[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// open testdata or ICU data converter ------------------------------------- ***
|
||||
|
@ -81,6 +81,7 @@ class NumberFormatterApiTest : public IntlTest {
|
||||
MeasureUnit SQUARE_MILE;
|
||||
MeasureUnit JOULE;
|
||||
MeasureUnit FURLONG;
|
||||
MeasureUnit KELVIN;
|
||||
|
||||
NumberingSystem MATHSANB;
|
||||
NumberingSystem LATN;
|
||||
@ -161,6 +162,7 @@ class PatternStringTest : public IntlTest {
|
||||
class NumberStringBuilderTest : public IntlTest {
|
||||
public:
|
||||
void testInsertAppendUnicodeString();
|
||||
void testSplice();
|
||||
void testInsertAppendCodePoint();
|
||||
void testCopy();
|
||||
void testFields();
|
||||
|
@ -42,6 +42,7 @@ NumberFormatterApiTest::NumberFormatterApiTest(UErrorCode &status)
|
||||
SQUARE_MILE = *LocalPointer<MeasureUnit>(MeasureUnit::createSquareMile(status));
|
||||
JOULE = *LocalPointer<MeasureUnit>(MeasureUnit::createJoule(status));
|
||||
FURLONG = *LocalPointer<MeasureUnit>(MeasureUnit::createFurlong(status));
|
||||
KELVIN = *LocalPointer<MeasureUnit>(MeasureUnit::createKelvin(status));
|
||||
|
||||
MATHSANB = *LocalPointer<NumberingSystem>(NumberingSystem::createInstanceByName("mathsanb", status));
|
||||
LATN = *LocalPointer<NumberingSystem>(NumberingSystem::createInstanceByName("latn", status));
|
||||
@ -464,6 +465,25 @@ void NumberFormatterApiTest::unitMeasure() {
|
||||
Locale("es-US"),
|
||||
5.43,
|
||||
u"5.43 °F");
|
||||
|
||||
assertFormatSingle(
|
||||
u"MeasureUnit form without {0} in CLDR pattern",
|
||||
NumberFormatter::with()
|
||||
.unit(KELVIN)
|
||||
.unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME),
|
||||
Locale("es-MX"),
|
||||
1,
|
||||
u"kelvin");
|
||||
|
||||
assertFormatSingle(
|
||||
u"MeasureUnit form without {0} in CLDR pattern and wide base form",
|
||||
NumberFormatter::with()
|
||||
.rounding(Rounder::fixedFraction(20))
|
||||
.unit(KELVIN)
|
||||
.unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME),
|
||||
Locale("es-MX"),
|
||||
1,
|
||||
u"kelvin");
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::unitCompoundMeasure() {
|
||||
|
@ -23,6 +23,7 @@ void NumberStringBuilderTest::runIndexedTest(int32_t index, UBool exec, const ch
|
||||
}
|
||||
TESTCASE_AUTO_BEGIN;
|
||||
TESTCASE_AUTO(testInsertAppendUnicodeString);
|
||||
TESTCASE_AUTO(testSplice);
|
||||
TESTCASE_AUTO(testInsertAppendCodePoint);
|
||||
TESTCASE_AUTO(testCopy);
|
||||
TESTCASE_AUTO(testFields);
|
||||
@ -75,6 +76,55 @@ void NumberStringBuilderTest::testInsertAppendUnicodeString() {
|
||||
}
|
||||
}
|
||||
|
||||
void NumberStringBuilderTest::testSplice() {
|
||||
const struct TestCase {
|
||||
const char16_t* input;
|
||||
const int32_t startThis;
|
||||
const int32_t endThis;
|
||||
} cases[] = {
|
||||
{ u"", 0, 0 },
|
||||
{ u"abc", 0, 0 },
|
||||
{ u"abc", 1, 1 },
|
||||
{ u"abc", 1, 2 },
|
||||
{ u"abc", 0, 2 },
|
||||
{ u"abc", 0, 3 },
|
||||
{ u"lorem ipsum dolor sit amet", 8, 8 },
|
||||
{ u"lorem ipsum dolor sit amet", 8, 11 }, // 3 chars, equal to replacement "xyz"
|
||||
{ u"lorem ipsum dolor sit amet", 8, 18 } }; // 10 chars, larger than several replacements
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UnicodeString sb1;
|
||||
NumberStringBuilder sb2;
|
||||
for (auto cas : cases) {
|
||||
for (const char16_t* replacementPtr : EXAMPLE_STRINGS) {
|
||||
UnicodeString replacement(replacementPtr);
|
||||
|
||||
// Test replacement with full string
|
||||
sb1.remove();
|
||||
sb1.append(cas.input);
|
||||
sb1.replace(cas.startThis, cas.endThis - cas.startThis, replacement);
|
||||
sb2.clear();
|
||||
sb2.append(cas.input, UNUM_FIELD_COUNT, status);
|
||||
sb2.splice(cas.startThis, cas.endThis, replacement, 0, replacement.length(), UNUM_FIELD_COUNT, status);
|
||||
assertSuccess("Splicing into sb2 first time", status);
|
||||
assertEqualsImpl(sb1, sb2);
|
||||
|
||||
// Test replacement with partial string
|
||||
if (replacement.length() <= 2) {
|
||||
continue;
|
||||
}
|
||||
sb1.remove();
|
||||
sb1.append(cas.input);
|
||||
sb1.replace(cas.startThis, cas.endThis - cas.startThis, UnicodeString(replacement, 1, 2));
|
||||
sb2.clear();
|
||||
sb2.append(cas.input, UNUM_FIELD_COUNT, status);
|
||||
sb2.splice(cas.startThis, cas.endThis, replacement, 1, 3, UNUM_FIELD_COUNT, status);
|
||||
assertSuccess("Splicing into sb2 second time", status);
|
||||
assertEqualsImpl(sb1, sb2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NumberStringBuilderTest::testInsertAppendCodePoint() {
|
||||
static const UChar32 cases[] = {
|
||||
0, 1, 60, 127, 128, 0x7fff, 0x8000, 0xffff, 0x10000, 0x1f000, 0x10ffff};
|
||||
@ -230,7 +280,8 @@ void NumberStringBuilderTest::assertEqualsImpl(const UnicodeString &a, const Num
|
||||
for (int32_t i = 0; i < a.length(); i++) {
|
||||
IntlTest::assertEquals(
|
||||
UnicodeString(u"Char at position ") + Int64ToUnicodeString(i) +
|
||||
UnicodeString(u" in string ") + a, a.charAt(i), b.charAt(i));
|
||||
UnicodeString(u" in \"") + a + UnicodeString("\" versus \"") +
|
||||
b.toUnicodeString() + UnicodeString("\""), a.charAt(i), b.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,12 +77,12 @@ tzorig: $(TZCODE) $(TZDATA)
|
||||
-mv $(TZORIG)/zishrink.awk $(TZORIG)/zishrink.awk.orig
|
||||
sed -e '/if (line ~ \/^R SystemV \/) return/s/^/#/' $(TZORIG)/zishrink.awk.orig > $(TZORIG)/zishrink.awk
|
||||
-mv $(TZORIG)/Makefile $(TZORIG)/Makefile.orig
|
||||
sed -e "s/BACKWARD=\$$(BACKWARD)/BACKWARD='\$$(BACKWARD)'/" $(TZORIG)/Makefile.orig > $(TZORIG)/Makefile
|
||||
sed -e "s/^BACKWARD=.*/BACKWARD= backward pacificnew/" $(TZORIG)/Makefile.orig > $(TZORIG)/Makefile
|
||||
$(MAKE) -C $@ $(TZORIG_OPTS) zdump zones
|
||||
|
||||
$(ZDUMPOUT): tzorig
|
||||
( cd $(TZORIG) ; ./zdump$(EXEEXT) $(ZDUMP_OPTS) )
|
||||
|
||||
find $(ZDUMPOUT) -name '*--ICU' -exec sh -c 'mv "$${0}" $${0%--ICU}' {} \;
|
||||
|
||||
dump-out: $(ZDUMPOUT) $(ICUZDUMPOUT)
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "uoptions.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace icu;
|
||||
|
||||
class DumpFormatter {
|
||||
public:
|
||||
|
@ -78,3 +78,52 @@ Link Asia/Ho_Chi_Minh VST
|
||||
#
|
||||
Link America/Regina Canada/East-Saskatchewan # removed from backward in 2017c
|
||||
|
||||
|
||||
# Note:
|
||||
# Following section was added for tz database 2018a and 2018b.
|
||||
# ICU has a bug handling negative DST, and we also don't want to
|
||||
# flip sumer time name and winter time name for Dublin at least for
|
||||
# now. Because the change had major impacts to tz database external
|
||||
# consumers, the tz database maintainer once reverted the Europe/Dublin
|
||||
# rules (same as 2017c or older) in 2018c. The tz database maintainer
|
||||
# thinks the changes in 2018a should be brought back when external
|
||||
# tz database consumers are ready to adopt the change. We don't know
|
||||
# what CLDR TC want to do with this for now. But if tz database brings
|
||||
# back the change, and CLDR TC (and ICU TC) want to keep the display name
|
||||
# unchanged, then we can uncomment the block below to restore ICU
|
||||
# custom override. (Yoshito 2018-01-23)
|
||||
|
||||
#
|
||||
# tzdata2018a changed Europe/Dublin to use IST (UTC+1) as the standard time
|
||||
# of the region, and GMT (UTC) as the daylight saving time with negative
|
||||
# offset (-1 hour) in winter. ICU SimpleTimeZone rejects a zone with negative
|
||||
# daylight saving time offset. We could remove the restriction in newer version
|
||||
# of ICU, but such data does not work well with older ICU runtime without
|
||||
# fixing the issue. For now, we define our own Europe/Dubin in ICU, replacing
|
||||
# Europe/Dublin data from the tz database.
|
||||
#
|
||||
|
||||
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
|
||||
# Rule Eire--ICU 1971 only - Oct 31 2:00u 0 GMT
|
||||
# Rule Eire--ICU 1972 1980 - Mar Sun>=16 2:00u 1:00 IST
|
||||
# Rule Eire--ICU 1972 1980 - Oct Sun>=23 2:00u 0 GMT
|
||||
# Rule Eire--ICU 1981 max - Mar lastSun 1:00u 1:00 IST
|
||||
# Rule Eire--ICU 1981 1989 - Oct Sun>=23 1:00u 0 GMT
|
||||
# Rule Eire--ICU 1990 1995 - Oct Sun>=22 1:00u 0 GMT
|
||||
# Rule Eire--ICU 1996 max - Oct lastSun 1:00u 0 GMT
|
||||
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
# Zone Europe/Dublin--ICU -0:25:00 - LMT 1880 Aug 2
|
||||
# -0:25:21 - DMT 1916 May 21 2:00s
|
||||
# -0:25:21 1:00 IST 1916 Oct 1 2:00s
|
||||
# 0:00 GB-Eire %s 1921 Dec 6 # independence
|
||||
# 0:00 GB-Eire GMT/IST 1940 Feb 25 2:00s
|
||||
# 0:00 1:00 IST 1946 Oct 6 2:00s
|
||||
# 0:00 - GMT 1947 Mar 16 2:00s
|
||||
# 0:00 1:00 IST 1947 Nov 2 2:00s
|
||||
# 0:00 - GMT 1948 Apr 18 2:00s
|
||||
# 0:00 GB-Eire GMT/IST 1968 Oct 27
|
||||
# 0:00 Eire--ICU GMT/IST
|
||||
|
||||
# Link Europe/Dublin--ICU Eire--ICU
|
||||
|
||||
|
@ -830,7 +830,7 @@ struct FinalRulePart {
|
||||
if (mode != DOM && (dow < 0 || dow >= 7)) {
|
||||
os << "Invalid input day of week " << dow;
|
||||
}
|
||||
if (offset < 0 || offset > (2 * HOUR)) {
|
||||
if (offset < (-1 * HOUR) || offset > (2 * HOUR)) {
|
||||
os << "Invalid input offset " << offset;
|
||||
}
|
||||
if (isgmt && !isstd) {
|
||||
@ -903,7 +903,6 @@ map<string,FinalRule> finalRules;
|
||||
|
||||
map<string, set<string> > links;
|
||||
map<string, string> reverseLinks;
|
||||
map<string, string> linkSource; // id => "Olson link" or "ICU alias"
|
||||
|
||||
/**
|
||||
* Predicate used to find FinalRule objects that do not have both
|
||||
@ -975,9 +974,6 @@ void readFinalZonesAndRules(istream& in) {
|
||||
|
||||
links[fromid].insert(toid);
|
||||
reverseLinks[toid] = fromid;
|
||||
|
||||
linkSource[fromid] = "Olson link";
|
||||
linkSource[toid] = "Olson link";
|
||||
} else if (token.length() > 0 && token[0] == '#') {
|
||||
consumeLine(in);
|
||||
} else {
|
||||
@ -1430,6 +1426,9 @@ void FinalRule::print(ostream& os) const {
|
||||
os << part[whichpart].offset << endl;
|
||||
}
|
||||
|
||||
#define ICU_ZONE_OVERRIDE_SUFFIX "--ICU"
|
||||
#define ICU_ZONE_OVERRIDE_SUFFIX_LEN 5
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
string rootpath, zonetab, version;
|
||||
bool validArgs = FALSE;
|
||||
@ -1493,6 +1492,82 @@ int main(int argc, char *argv[]) {
|
||||
<< (ZONEINFO.begin())->first << ".."
|
||||
<< (--ZONEINFO.end())->first << "]" << endl;
|
||||
|
||||
// Overrides TZ database zones with ICU custom zone definition.
|
||||
// These ICU zone overrides are defined in icuzones, with suffix --ICU.
|
||||
// If there is a matching TZ database zone, the zoneinfo is replaced
|
||||
// with the ICU definition. Then, the zone ID with --ICU suffix
|
||||
// will be deleted from the final list.
|
||||
// For example, zoneinfo for Europe/Dublin imported from the TZ database
|
||||
// will be replaced with the zone definition for Europe/Dublin--ICU
|
||||
// in icuzones.
|
||||
|
||||
// Collect zone IDs to be modified with ICU definition.
|
||||
vector<string> customZones;
|
||||
for (ZoneMapIter i = ZONEINFO.begin(); i != ZONEINFO.end(); ++i) {
|
||||
const string& id = i->first;
|
||||
size_t idx = id.rfind(ICU_ZONE_OVERRIDE_SUFFIX);
|
||||
if (idx != string::npos && idx == id.length() - ICU_ZONE_OVERRIDE_SUFFIX_LEN) {
|
||||
cout << "ICU zone override: " << id << endl;
|
||||
customZones.push_back(id.substr(0, idx));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// BEGIN ICU Custom ZoneInfo Override Handling
|
||||
//
|
||||
|
||||
// Replace zoneinfo with ICU definition, then remove ICU zone ID with
|
||||
// the special suffix.
|
||||
for (vector<string>::iterator i = customZones.begin(); i != customZones.end(); i++) {
|
||||
string& origId = *i;
|
||||
string custId = origId + ICU_ZONE_OVERRIDE_SUFFIX;
|
||||
|
||||
map<string,ZoneInfo>::iterator origZi = ZONEINFO.find(origId);
|
||||
map<string,ZoneInfo>::iterator custZi = ZONEINFO.find(custId);
|
||||
if (origZi != ZONEINFO.end() && custZi != ZONEINFO.end()) {
|
||||
// replace original zone info with custom override,
|
||||
// then delete one custom ID
|
||||
cout << "Replacing ZoneInfo " << origId << " with " << custId << endl;
|
||||
origZi->second = custZi->second;
|
||||
ZONEINFO.erase(custZi);
|
||||
}
|
||||
|
||||
// Also replace final rule
|
||||
map<string,FinalZone>::iterator origFz = finalZones.find(origId);
|
||||
map<string,FinalZone>::iterator custFz = finalZones.find(custId);
|
||||
if (origFz != finalZones.end() && custFz != finalZones.end()) {
|
||||
// replace original final zone with custom override,
|
||||
// then delete one for custom ID
|
||||
cout << "Replacing FinalZone for " << origId << " with " << custId << endl;
|
||||
origFz->second = custFz->second;
|
||||
finalZones.erase(custFz);
|
||||
}
|
||||
}
|
||||
|
||||
// Also remove aliases for ICU custom zoneinfo overrides.
|
||||
for (map<string,set<string>>::const_iterator i = links.begin(); i != links.end(); ) {
|
||||
const string& id = i->first;
|
||||
size_t idx = id.rfind(ICU_ZONE_OVERRIDE_SUFFIX);
|
||||
if (idx != string::npos && idx == id.length() - ICU_ZONE_OVERRIDE_SUFFIX_LEN) {
|
||||
const set<string>& aliases = i->second;
|
||||
// Also remove all revserse links
|
||||
for (set<string>::const_iterator j = aliases.begin(); j != aliases.end(); j++) {
|
||||
const string& alias = *j;
|
||||
cout << "Removing alias " << alias << endl;
|
||||
reverseLinks.erase(alias);
|
||||
}
|
||||
|
||||
links.erase(i++);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// END ICU Custom ZoneInfo Override Handling
|
||||
//
|
||||
|
||||
try {
|
||||
for_each(finalZones.begin(), finalZones.end(), mergeFinalZone);
|
||||
} catch (const exception& error) {
|
||||
@ -1510,7 +1585,7 @@ int main(int argc, char *argv[]) {
|
||||
const string& olson = i->first;
|
||||
const set<string>& aliases = i->second;
|
||||
if (ZONEINFO.find(olson) == ZONEINFO.end()) {
|
||||
cerr << "Error: Invalid " << linkSource[olson] << " to non-existent \""
|
||||
cerr << "Error: Invalid 'Link' to non-existent \""
|
||||
<< olson << "\"" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ public class LongNameHandler implements MicroPropsGenerator {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (StandardPlural plural : StandardPlural.VALUES) {
|
||||
String simpleFormat = getWithPlural(simpleFormats, plural);
|
||||
String compiled = SimpleFormatterImpl.compileToStringMinMaxArguments(simpleFormat, sb, 1, 1);
|
||||
String compiled = SimpleFormatterImpl.compileToStringMinMaxArguments(simpleFormat, sb, 0, 1);
|
||||
output.put(plural, new SimpleModifier(compiled, field, false));
|
||||
}
|
||||
}
|
||||
@ -261,7 +261,7 @@ public class LongNameHandler implements MicroPropsGenerator {
|
||||
String leadFormat = getWithPlural(leadFormats, plural);
|
||||
String compoundFormat = SimpleFormatterImpl.formatCompiledPattern(trailCompiled, leadFormat);
|
||||
String compoundCompiled = SimpleFormatterImpl
|
||||
.compileToStringMinMaxArguments(compoundFormat, sb, 1, 1);
|
||||
.compileToStringMinMaxArguments(compoundFormat, sb, 0, 1);
|
||||
output.put(plural, new SimpleModifier(compoundCompiled, field, false));
|
||||
}
|
||||
}
|
||||
|
@ -171,6 +171,39 @@ public class NumberStringBuilder implements CharSequence {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the chars between startThis and endThis with the chars between startOther and endOther of
|
||||
* the given CharSequence. Calling this method with startThis == endThis is equivalent to calling
|
||||
* insert.
|
||||
*
|
||||
* @return The number of chars added, which may be negative if the removed segment is longer than the
|
||||
* length of the CharSequence segment that was inserted.
|
||||
*/
|
||||
public int splice(
|
||||
int startThis,
|
||||
int endThis,
|
||||
CharSequence sequence,
|
||||
int startOther,
|
||||
int endOther,
|
||||
Field field) {
|
||||
int thisLength = endThis - startThis;
|
||||
int otherLength = endOther - startOther;
|
||||
int count = otherLength - thisLength;
|
||||
int position;
|
||||
if (count > 0) {
|
||||
// Overall, chars need to be added.
|
||||
position = prepareForInsert(startThis, count);
|
||||
} else {
|
||||
// Overall, chars need to be removed or kept the same.
|
||||
position = remove(startThis, -count);
|
||||
}
|
||||
for (int i = 0; i < otherLength; i++) {
|
||||
chars[position + i] = sequence.charAt(startOther + i);
|
||||
fields[position + i] = field;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the chars in the specified char array to the end of the string, and associates them with
|
||||
* the fields in the specified field array, which must have the same length as chars.
|
||||
@ -313,6 +346,18 @@ public class NumberStringBuilder implements CharSequence {
|
||||
return zero + index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the "count" chars starting at "index". Returns the position at which the chars were
|
||||
* removed.
|
||||
*/
|
||||
private int remove(int index, int count) {
|
||||
int position = index + zero;
|
||||
System.arraycopy(chars, position + count, chars, position, length - index - count);
|
||||
System.arraycopy(fields, position + count, fields, position, length - index - count);
|
||||
length -= count;
|
||||
return position;
|
||||
}
|
||||
|
||||
private int getCapacity() {
|
||||
return chars.length;
|
||||
}
|
||||
|
@ -27,18 +27,28 @@ public class SimpleModifier implements Modifier {
|
||||
this.field = field;
|
||||
this.strong = strong;
|
||||
|
||||
assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
|
||||
if (compiledPattern.charAt(1) != '\u0000') {
|
||||
int argLimit = SimpleFormatterImpl.getArgumentLimit(compiledPattern);
|
||||
if (argLimit == 0) {
|
||||
// No arguments in compiled pattern
|
||||
prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
|
||||
suffixOffset = 3 + prefixLength;
|
||||
} else {
|
||||
prefixLength = 0;
|
||||
suffixOffset = 2;
|
||||
}
|
||||
if (3 + prefixLength < compiledPattern.length()) {
|
||||
suffixLength = compiledPattern.charAt(suffixOffset) - ARG_NUM_LIMIT;
|
||||
} else {
|
||||
assert 2 + prefixLength == compiledPattern.length();
|
||||
// Set suffixOffset = -1 to indicate no arguments in compiled pattern.
|
||||
suffixOffset = -1;
|
||||
suffixLength = 0;
|
||||
} else {
|
||||
assert argLimit == 1;
|
||||
if (compiledPattern.charAt(1) != '\u0000') {
|
||||
prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
|
||||
suffixOffset = 3 + prefixLength;
|
||||
} else {
|
||||
prefixLength = 0;
|
||||
suffixOffset = 2;
|
||||
}
|
||||
if (3 + prefixLength < compiledPattern.length()) {
|
||||
suffixLength = compiledPattern.charAt(suffixOffset) - ARG_NUM_LIMIT;
|
||||
} else {
|
||||
suffixLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,16 +106,21 @@ public class SimpleModifier implements Modifier {
|
||||
int startIndex,
|
||||
int endIndex,
|
||||
Field field) {
|
||||
if (prefixLength > 0) {
|
||||
result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
|
||||
if (suffixOffset == -1) {
|
||||
// There is no argument for the inner number; overwrite the entire segment with our string.
|
||||
return result.splice(startIndex, endIndex, compiledPattern, 2, 2 + prefixLength, field);
|
||||
} else {
|
||||
if (prefixLength > 0) {
|
||||
result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
|
||||
}
|
||||
if (suffixLength > 0) {
|
||||
result.insert(endIndex + prefixLength,
|
||||
compiledPattern,
|
||||
1 + suffixOffset,
|
||||
1 + suffixOffset + suffixLength,
|
||||
field);
|
||||
}
|
||||
return prefixLength + suffixLength;
|
||||
}
|
||||
if (suffixLength > 0) {
|
||||
result.insert(endIndex + prefixLength,
|
||||
compiledPattern,
|
||||
1 + suffixOffset,
|
||||
1 + suffixOffset + suffixLength,
|
||||
field);
|
||||
}
|
||||
return prefixLength + suffixLength;
|
||||
}
|
||||
}
|
||||
|
@ -21,12 +21,11 @@ import com.ibm.icu.util.Measure;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
/**
|
||||
* Temporary internal concrete subclass of MeasureFormat implementing
|
||||
* parsing and formatting of CurrencyAmount objects. This class is
|
||||
* likely to be redesigned and rewritten in the near future.
|
||||
* Temporary internal concrete subclass of MeasureFormat implementing parsing and formatting of
|
||||
* CurrencyAmount objects. This class is likely to be redesigned and rewritten in the near future.
|
||||
*
|
||||
* <p>This class currently delegates to DecimalFormat for parsing and
|
||||
* formatting.
|
||||
* <p>
|
||||
* This class currently delegates to DecimalFormat for parsing and formatting.
|
||||
*
|
||||
* @see com.ibm.icu.text.UFormat
|
||||
* @see com.ibm.icu.text.DecimalFormat
|
||||
@ -35,7 +34,7 @@ import com.ibm.icu.util.ULocale;
|
||||
class CurrencyFormat extends MeasureFormat {
|
||||
// Generated by serialver from JDK 1.4.1_01
|
||||
static final long serialVersionUID = -931679363692504634L;
|
||||
|
||||
|
||||
private NumberFormat fmt;
|
||||
private transient final MeasureFormat mf;
|
||||
|
||||
@ -45,7 +44,7 @@ class CurrencyFormat extends MeasureFormat {
|
||||
mf = MeasureFormat.getInstance(locale, FormatWidth.WIDE);
|
||||
fmt = NumberFormat.getCurrencyInstance(locale.toLocale());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -58,39 +57,44 @@ class CurrencyFormat extends MeasureFormat {
|
||||
|
||||
/**
|
||||
* Override Format.format().
|
||||
*
|
||||
* @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
|
||||
*/
|
||||
@Override
|
||||
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
|
||||
if (!(obj instanceof CurrencyAmount)) {
|
||||
throw new IllegalArgumentException("Invalid type: " + obj.getClass().getName());
|
||||
}
|
||||
CurrencyAmount currency = (CurrencyAmount) obj;
|
||||
|
||||
|
||||
fmt.setCurrency(currency.getCurrency());
|
||||
return fmt.format(currency.getNumber(), toAppendTo, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override Format.parseObject().
|
||||
*
|
||||
* @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
|
||||
*/
|
||||
@Override
|
||||
public CurrencyAmount parseObject(String source, ParsePosition pos) {
|
||||
return fmt.parseCurrency(source, pos);
|
||||
}
|
||||
|
||||
|
||||
// boilerplate code to make CurrencyFormat otherwise follow the contract of
|
||||
// MeasureFormat
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public StringBuilder formatMeasures(
|
||||
StringBuilder appendTo, FieldPosition fieldPosition, Measure... measures) {
|
||||
StringBuilder appendTo,
|
||||
FieldPosition fieldPosition,
|
||||
Measure... measures) {
|
||||
return mf.formatMeasures(appendTo, fieldPosition, measures);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -98,7 +102,7 @@ class CurrencyFormat extends MeasureFormat {
|
||||
public MeasureFormat.FormatWidth getWidth() {
|
||||
return mf.getWidth();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -106,15 +110,15 @@ class CurrencyFormat extends MeasureFormat {
|
||||
public NumberFormat getNumberFormat() {
|
||||
return mf.getNumberFormat();
|
||||
}
|
||||
|
||||
|
||||
// End boilerplate.
|
||||
|
||||
|
||||
// Serialization
|
||||
|
||||
|
||||
private Object writeReplace() throws ObjectStreamException {
|
||||
return mf.toCurrencyProxy();
|
||||
}
|
||||
|
||||
|
||||
// Preserve backward serialize backward compatibility.
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return new CurrencyFormat(fmt.getLocale(ULocale.ACTUAL_LOCALE));
|
||||
|
@ -260,7 +260,7 @@ public class CurrencyPluralInfo implements Cloneable, Serializable {
|
||||
* @deprecated This API is ICU internal only.
|
||||
*/
|
||||
@Deprecated
|
||||
String select(PluralRules.FixedDecimal numberInfo) {
|
||||
public String select(PluralRules.FixedDecimal numberInfo) {
|
||||
return pluralRules.select(numberInfo);
|
||||
}
|
||||
|
||||
@ -268,8 +268,11 @@ public class CurrencyPluralInfo implements Cloneable, Serializable {
|
||||
* Currency plural pattern iterator.
|
||||
*
|
||||
* @return a iterator on the currency plural pattern key set.
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
*/
|
||||
Iterator<String> pluralPatternIterator() {
|
||||
@Deprecated
|
||||
public Iterator<String> pluralPatternIterator() {
|
||||
return pluralCountToCurrencyUnitPattern.keySet().iterator();
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,34 +30,35 @@ import com.ibm.icu.util.ULocale;
|
||||
import com.ibm.icu.util.ULocale.Category;
|
||||
import com.ibm.icu.util.UResourceBundle;
|
||||
|
||||
|
||||
/**
|
||||
* Format or parse a TimeUnitAmount, using plural rules for the units where available.
|
||||
*
|
||||
* <P>
|
||||
* Code Sample:
|
||||
*
|
||||
* <pre>
|
||||
* // create a time unit instance.
|
||||
* // only SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, and YEAR are supported
|
||||
* TimeUnit timeUnit = TimeUnit.SECOND;
|
||||
* // create time unit amount instance - a combination of Number and time unit
|
||||
* TimeUnitAmount source = new TimeUnitAmount(2, timeUnit);
|
||||
* // create time unit format instance
|
||||
* TimeUnitFormat format = new TimeUnitFormat();
|
||||
* // set the locale of time unit format
|
||||
* format.setLocale(new ULocale("en"));
|
||||
* // format a time unit amount
|
||||
* String formatted = format.format(source);
|
||||
* System.out.println(formatted);
|
||||
* try {
|
||||
* // parse a string into time unit amount
|
||||
* TimeUnitAmount result = (TimeUnitAmount) format.parseObject(formatted);
|
||||
* // result should equal to source
|
||||
* } catch (ParseException e) {
|
||||
* }
|
||||
* // create a time unit instance.
|
||||
* // only SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, and YEAR are supported
|
||||
* TimeUnit timeUnit = TimeUnit.SECOND;
|
||||
* // create time unit amount instance - a combination of Number and time unit
|
||||
* TimeUnitAmount source = new TimeUnitAmount(2, timeUnit);
|
||||
* // create time unit format instance
|
||||
* TimeUnitFormat format = new TimeUnitFormat();
|
||||
* // set the locale of time unit format
|
||||
* format.setLocale(new ULocale("en"));
|
||||
* // format a time unit amount
|
||||
* String formatted = format.format(source);
|
||||
* System.out.println(formatted);
|
||||
* try {
|
||||
* // parse a string into time unit amount
|
||||
* TimeUnitAmount result = (TimeUnitAmount) format.parseObject(formatted);
|
||||
* // result should equal to source
|
||||
* } catch (ParseException e) {
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <P>
|
||||
*
|
||||
* @see TimeUnitAmount
|
||||
* @see MeasureFormat
|
||||
* @author markdavis
|
||||
@ -67,15 +68,17 @@ import com.ibm.icu.util.UResourceBundle;
|
||||
public class TimeUnitFormat extends MeasureFormat {
|
||||
|
||||
/**
|
||||
* Constant for full name style format.
|
||||
* For example, the full name for "hour" in English is "hour" or "hours".
|
||||
* Constant for full name style format. For example, the full name for "hour" in English is "hour" or
|
||||
* "hours".
|
||||
*
|
||||
* @deprecated ICU 53 see {@link MeasureFormat.FormatWidth}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int FULL_NAME = 0;
|
||||
/**
|
||||
* Constant for abbreviated name style format.
|
||||
* For example, the abbreviated name for "hour" in English is "hr" or "hrs".
|
||||
* Constant for abbreviated name style format. For example, the abbreviated name for "hour" in
|
||||
* English is "hr" or "hrs".
|
||||
*
|
||||
* @deprecated ICU 53 see {@link MeasureFormat.FormatWidth}
|
||||
*/
|
||||
@Deprecated
|
||||
@ -111,8 +114,9 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
private static final String DEFAULT_PATTERN_FOR_YEAR = "{0} y";
|
||||
|
||||
/**
|
||||
* Create empty format using full name style, for example, "hours".
|
||||
* Use setLocale and/or setFormat to modify.
|
||||
* Create empty format using full name style, for example, "hours". Use setLocale and/or setFormat to
|
||||
* modify.
|
||||
*
|
||||
* @deprecated ICU 53 use {@link MeasureFormat} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@ -124,7 +128,9 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
|
||||
/**
|
||||
* Create TimeUnitFormat given a ULocale, and using full name style.
|
||||
* @param locale locale of this time unit formatter.
|
||||
*
|
||||
* @param locale
|
||||
* locale of this time unit formatter.
|
||||
* @deprecated ICU 53 use {@link MeasureFormat} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@ -134,7 +140,9 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
|
||||
/**
|
||||
* Create TimeUnitFormat given a Locale, and using full name style.
|
||||
* @param locale locale of this time unit formatter.
|
||||
*
|
||||
* @param locale
|
||||
* locale of this time unit formatter.
|
||||
* @deprecated ICU 53 use {@link MeasureFormat} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@ -144,19 +152,23 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
|
||||
/**
|
||||
* Create TimeUnitFormat given a ULocale and a formatting style.
|
||||
* @param locale locale of this time unit formatter.
|
||||
* @param style format style, either FULL_NAME or ABBREVIATED_NAME style.
|
||||
* @throws IllegalArgumentException if the style is not FULL_NAME or
|
||||
* ABBREVIATED_NAME style.
|
||||
*
|
||||
* @param locale
|
||||
* locale of this time unit formatter.
|
||||
* @param style
|
||||
* format style, either FULL_NAME or ABBREVIATED_NAME style.
|
||||
* @throws IllegalArgumentException
|
||||
* if the style is not FULL_NAME or ABBREVIATED_NAME style.
|
||||
* @deprecated ICU 53 use {@link MeasureFormat} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public TimeUnitFormat(ULocale locale, int style) {
|
||||
if (style < FULL_NAME || style >= TOTAL_STYLES) {
|
||||
throw new IllegalArgumentException("style should be either FULL_NAME or ABBREVIATED_NAME style");
|
||||
throw new IllegalArgumentException(
|
||||
"style should be either FULL_NAME or ABBREVIATED_NAME style");
|
||||
}
|
||||
mf = MeasureFormat.getInstance(
|
||||
locale, style == FULL_NAME ? FormatWidth.WIDE : FormatWidth.SHORT);
|
||||
mf = MeasureFormat.getInstance(locale,
|
||||
style == FULL_NAME ? FormatWidth.WIDE : FormatWidth.SHORT);
|
||||
this.style = style;
|
||||
|
||||
// Needed for getLocale(ULocale.VALID_LOCALE)
|
||||
@ -174,22 +186,25 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
|
||||
/**
|
||||
* Create TimeUnitFormat given a Locale and a formatting style.
|
||||
*
|
||||
* @deprecated ICU 53 use {@link MeasureFormat} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public TimeUnitFormat(Locale locale, int style) {
|
||||
this(ULocale.forLocale(locale), style);
|
||||
this(ULocale.forLocale(locale), style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the locale used for formatting or parsing.
|
||||
* @param locale locale of this time unit formatter.
|
||||
*
|
||||
* @param locale
|
||||
* locale of this time unit formatter.
|
||||
* @return this, for chaining.
|
||||
* @deprecated ICU 53 see {@link MeasureFormat}.
|
||||
*/
|
||||
@Deprecated
|
||||
public TimeUnitFormat setLocale(ULocale locale) {
|
||||
if (locale != this.locale){
|
||||
if (locale != this.locale) {
|
||||
mf = mf.withLocale(locale);
|
||||
|
||||
// Needed for getLocale(ULocale.VALID_LOCALE)
|
||||
@ -202,7 +217,9 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
|
||||
/**
|
||||
* Set the locale used for formatting or parsing.
|
||||
* @param locale locale of this time unit formatter.
|
||||
*
|
||||
* @param locale
|
||||
* locale of this time unit formatter.
|
||||
* @return this, for chaining.
|
||||
* @deprecated ICU 53 see {@link MeasureFormat}.
|
||||
*/
|
||||
@ -214,7 +231,9 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
/**
|
||||
* Set the format used for formatting or parsing. Passing null is equivalent to passing
|
||||
* {@link NumberFormat#getNumberInstance(ULocale)}.
|
||||
* @param format the number formatter.
|
||||
*
|
||||
* @param format
|
||||
* the number formatter.
|
||||
* @return this, for chaining.
|
||||
* @deprecated ICU 53 see {@link MeasureFormat}.
|
||||
*/
|
||||
@ -238,20 +257,21 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format a TimeUnitAmount.
|
||||
*
|
||||
* @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
|
||||
* @deprecated ICU 53 see {@link MeasureFormat}.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public StringBuffer format(Object obj, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
|
||||
return mf.format(obj, toAppendTo, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a TimeUnitAmount.
|
||||
*
|
||||
* @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
|
||||
* @deprecated ICU 53 see {@link MeasureFormat}.
|
||||
*/
|
||||
@ -293,9 +313,11 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
if (tempObj instanceof Number) {
|
||||
temp = (Number) tempObj;
|
||||
} else {
|
||||
// Since we now format the number ourselves, parseObject will likely give us back a String
|
||||
// Since we now format the number ourselves, parseObject will likely give us
|
||||
// back a String
|
||||
// for
|
||||
// the number. When this happens we must parse the formatted number ourselves.
|
||||
// the number. When this happens we must parse the formatted number
|
||||
// ourselves.
|
||||
try {
|
||||
temp = format.parse(tempObj.toString());
|
||||
} catch (ParseException e) {
|
||||
@ -315,8 +337,9 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
}
|
||||
}
|
||||
/*
|
||||
* After find the longest match, parse the number. Result number could be null for the pattern without number
|
||||
* pattern. such as unit pattern in Arabic. When result number is null, use plural rule to set the number.
|
||||
* After find the longest match, parse the number. Result number could be null for the pattern
|
||||
* without number pattern. such as unit pattern in Arabic. When result number is null, use plural
|
||||
* rule to set the number.
|
||||
*/
|
||||
if (resultNumber == null && longestParseDistance != 0) {
|
||||
// set the number using plurrual count
|
||||
@ -371,8 +394,11 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
ULocale locale;
|
||||
boolean beenHere;
|
||||
|
||||
TimeUnitFormatSetupSink(Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns,
|
||||
int style, Set<String> pluralKeywords, ULocale locale) {
|
||||
TimeUnitFormatSetupSink(
|
||||
Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns,
|
||||
int style,
|
||||
Set<String> pluralKeywords,
|
||||
ULocale locale) {
|
||||
this.timeUnitToCountToPatterns = timeUnitToCountToPatterns;
|
||||
this.style = style;
|
||||
this.pluralKeywords = pluralKeywords;
|
||||
@ -388,7 +414,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
} else {
|
||||
beenHere = true;
|
||||
}
|
||||
|
||||
|
||||
UResource.Table units = value.getTable();
|
||||
for (int i = 0; units.getKeyAndValue(i, key, value); ++i) {
|
||||
String timeUnitName = key.toString();
|
||||
@ -442,16 +468,21 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
}
|
||||
}
|
||||
|
||||
private void setup(String resourceKey, Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns, int style,
|
||||
private void setup(
|
||||
String resourceKey,
|
||||
Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns,
|
||||
int style,
|
||||
Set<String> pluralKeywords) {
|
||||
// fill timeUnitToCountToPatterns from resource file
|
||||
try {
|
||||
|
||||
ICUResourceBundle resource = (ICUResourceBundle) UResourceBundle.getBundleInstance(
|
||||
ICUData.ICU_UNIT_BASE_NAME, locale);
|
||||
ICUResourceBundle resource = (ICUResourceBundle) UResourceBundle
|
||||
.getBundleInstance(ICUData.ICU_UNIT_BASE_NAME, locale);
|
||||
|
||||
TimeUnitFormatSetupSink sink = new TimeUnitFormatSetupSink(
|
||||
timeUnitToCountToPatterns, style, pluralKeywords, locale);
|
||||
TimeUnitFormatSetupSink sink = new TimeUnitFormatSetupSink(timeUnitToCountToPatterns,
|
||||
style,
|
||||
pluralKeywords,
|
||||
locale);
|
||||
resource.getAllItemsWithFallback(resourceKey, sink);
|
||||
} catch (MissingResourceException e) {
|
||||
}
|
||||
@ -485,9 +516,15 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
timeUnitToCountToPatterns.put(timeUnit, countToPatterns);
|
||||
}
|
||||
for (String pluralCount : keywords) {
|
||||
if (countToPatterns.get(pluralCount) == null || countToPatterns.get(pluralCount)[style] == null) {
|
||||
if (countToPatterns.get(pluralCount) == null
|
||||
|| countToPatterns.get(pluralCount)[style] == null) {
|
||||
// look through parents
|
||||
searchInTree(resourceKey, style, timeUnit, pluralCount, pluralCount, countToPatterns);
|
||||
searchInTree(resourceKey,
|
||||
style,
|
||||
timeUnit,
|
||||
pluralCount,
|
||||
pluralCount,
|
||||
countToPatterns);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -501,15 +538,20 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
// if the pattern is not found even in root, fallback to
|
||||
// using patterns of plural count "other",
|
||||
// then, "other" is the searchPluralCount.
|
||||
private void searchInTree(String resourceKey, int styl, TimeUnit timeUnit, String srcPluralCount,
|
||||
String searchPluralCount, Map<String, Object[]> countToPatterns) {
|
||||
private void searchInTree(
|
||||
String resourceKey,
|
||||
int styl,
|
||||
TimeUnit timeUnit,
|
||||
String srcPluralCount,
|
||||
String searchPluralCount,
|
||||
Map<String, Object[]> countToPatterns) {
|
||||
ULocale parentLocale = locale;
|
||||
String srcTimeUnitName = timeUnit.toString();
|
||||
while (parentLocale != null) {
|
||||
try {
|
||||
// look for pattern for srcPluralCount in locale tree
|
||||
ICUResourceBundle unitsRes = (ICUResourceBundle) UResourceBundle.getBundleInstance(
|
||||
ICUData.ICU_UNIT_BASE_NAME, parentLocale);
|
||||
ICUResourceBundle unitsRes = (ICUResourceBundle) UResourceBundle
|
||||
.getBundleInstance(ICUData.ICU_UNIT_BASE_NAME, parentLocale);
|
||||
unitsRes = unitsRes.getWithFallback(resourceKey);
|
||||
ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(srcTimeUnitName);
|
||||
String pattern = oneUnitRes.getStringWithFallback(searchPluralCount);
|
||||
@ -569,7 +611,6 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
// boilerplate code to make TimeUnitFormat otherwise follow the contract of
|
||||
// MeasureFormat
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
@ -577,7 +618,9 @@ public class TimeUnitFormat extends MeasureFormat {
|
||||
@Deprecated
|
||||
@Override
|
||||
public StringBuilder formatMeasures(
|
||||
StringBuilder appendTo, FieldPosition fieldPosition, Measure... measures) {
|
||||
StringBuilder appendTo,
|
||||
FieldPosition fieldPosition,
|
||||
Measure... measures) {
|
||||
return mf.formatMeasures(appendTo, fieldPosition, measures);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:49fc6a589685cd6252d1bcfc9fd694b1ef3a298db2875eb0e655111770d0f7f6
|
||||
size 12475718
|
||||
oid sha256:5dc7e055663128ae9a1dae471f9a7cdaf5c28e8177b2231e8b0341c3dc8bb842
|
||||
size 12475727
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9ab0aa84333a23a0e40f5641d96d4b12e0f7acc10b3ca32a98141d04af1ef59b
|
||||
size 92714
|
||||
oid sha256:00c43dc113177aa5a0ffda563ac2822f3dc92fdb7ae748a5938529e32a0b67d9
|
||||
size 92739
|
||||
|
@ -1,10 +1,13 @@
|
||||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.impl.number;
|
||||
package com.ibm.icu.dev.impl.number;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import com.ibm.icu.impl.number.DecimalQuantity;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity_AbstractBCD;
|
||||
|
||||
public final class DecimalQuantity_64BitBCD extends DecimalQuantity_AbstractBCD {
|
||||
|
||||
/**
|
@ -1,10 +1,13 @@
|
||||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.impl.number;
|
||||
package com.ibm.icu.dev.impl.number;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import com.ibm.icu.impl.number.DecimalQuantity;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity_AbstractBCD;
|
||||
|
||||
public final class DecimalQuantity_ByteArrayBCD extends DecimalQuantity_AbstractBCD {
|
||||
|
||||
/**
|
@ -1,6 +1,6 @@
|
||||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.impl.number;
|
||||
package com.ibm.icu.dev.impl.number;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
@ -9,6 +9,7 @@ import java.text.ParsePosition;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.icu.dev.test.TestUtil;
|
||||
import com.ibm.icu.dev.text.DecimalFormat_ICU58;
|
||||
import com.ibm.icu.impl.number.DecimalFormatProperties;
|
||||
import com.ibm.icu.impl.number.Padder.PadPosition;
|
||||
import com.ibm.icu.impl.number.PatternStringParser;
|
||||
@ -20,7 +21,6 @@ import com.ibm.icu.number.NumberFormatter;
|
||||
import com.ibm.icu.text.DecimalFormat;
|
||||
import com.ibm.icu.text.DecimalFormat.PropertySetter;
|
||||
import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
import com.ibm.icu.text.DecimalFormat_ICU58;
|
||||
import com.ibm.icu.util.CurrencyAmount;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
|
@ -43,6 +43,7 @@ import org.junit.runners.JUnit4;
|
||||
import com.ibm.icu.dev.test.TestFmwk;
|
||||
import com.ibm.icu.dev.test.TestUtil;
|
||||
import com.ibm.icu.dev.test.format.IntlTestDecimalFormatAPIC.FieldContainer;
|
||||
import com.ibm.icu.dev.text.DecimalFormat_ICU58;
|
||||
import com.ibm.icu.impl.ICUConfig;
|
||||
import com.ibm.icu.impl.LocaleUtility;
|
||||
import com.ibm.icu.impl.data.ResourceReader;
|
||||
@ -55,7 +56,6 @@ import com.ibm.icu.text.CurrencyPluralInfo;
|
||||
import com.ibm.icu.text.DecimalFormat;
|
||||
import com.ibm.icu.text.DecimalFormat.PropertySetter;
|
||||
import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
import com.ibm.icu.text.DecimalFormat_ICU58;
|
||||
import com.ibm.icu.text.DisplayContext;
|
||||
import com.ibm.icu.text.MeasureFormat;
|
||||
import com.ibm.icu.text.NumberFormat;
|
||||
|
@ -16,13 +16,13 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import com.ibm.icu.dev.impl.number.DecimalQuantity_64BitBCD;
|
||||
import com.ibm.icu.dev.impl.number.DecimalQuantity_ByteArrayBCD;
|
||||
import com.ibm.icu.dev.impl.number.DecimalQuantity_SimpleStorage;
|
||||
import com.ibm.icu.dev.test.TestFmwk;
|
||||
import com.ibm.icu.impl.number.DecimalFormatProperties;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity_64BitBCD;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity_ByteArrayBCD;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
|
||||
import com.ibm.icu.impl.number.DecimalQuantity_SimpleStorage;
|
||||
import com.ibm.icu.number.LocalizedNumberFormatter;
|
||||
import com.ibm.icu.number.NumberFormatter;
|
||||
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
|
||||
|
@ -473,6 +473,25 @@ public class NumberFormatterApiTest {
|
||||
ULocale.forLanguageTag("es-US"),
|
||||
5.43,
|
||||
"5.43 °F");
|
||||
|
||||
assertFormatSingle(
|
||||
"MeasureUnit form without {0} in CLDR pattern",
|
||||
"",
|
||||
NumberFormatter.with().unit(MeasureUnit.KELVIN).unitWidth(UnitWidth.FULL_NAME),
|
||||
ULocale.forLanguageTag("es-MX"),
|
||||
1,
|
||||
"kelvin");
|
||||
|
||||
assertFormatSingle(
|
||||
"MeasureUnit form without {0} in CLDR pattern and wide base form",
|
||||
"",
|
||||
NumberFormatter.with()
|
||||
.rounding(Rounder.fixedFraction(20))
|
||||
.unit(MeasureUnit.KELVIN)
|
||||
.unitWidth(UnitWidth.FULL_NAME),
|
||||
ULocale.forLanguageTag("es-MX"),
|
||||
1,
|
||||
"kelvin");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -68,6 +68,50 @@ public class NumberStringBuilderTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplice() {
|
||||
Object[][] cases = {
|
||||
{ "", 0, 0 },
|
||||
{ "abc", 0, 0 },
|
||||
{ "abc", 1, 1 },
|
||||
{ "abc", 1, 2 },
|
||||
{ "abc", 0, 2 },
|
||||
{ "abc", 0, 3 },
|
||||
{ "lorem ipsum dolor sit amet", 8, 8 },
|
||||
{ "lorem ipsum dolor sit amet", 8, 11 }, // 3 chars, equal to replacement "xyz"
|
||||
{ "lorem ipsum dolor sit amet", 8, 18 } }; // 10 chars, larger than several replacements
|
||||
|
||||
StringBuilder sb1 = new StringBuilder();
|
||||
NumberStringBuilder sb2 = new NumberStringBuilder();
|
||||
for (Object[] cas : cases) {
|
||||
String input = (String) cas[0];
|
||||
int startThis = (Integer) cas[1];
|
||||
int endThis = (Integer) cas[2];
|
||||
for (String replacement : EXAMPLE_STRINGS) {
|
||||
// Test replacement with full string
|
||||
sb1.setLength(0);
|
||||
sb1.append(input);
|
||||
sb1.replace(startThis, endThis, replacement);
|
||||
sb2.clear();
|
||||
sb2.append(input, null);
|
||||
sb2.splice(startThis, endThis, replacement, 0, replacement.length(), null);
|
||||
assertCharSequenceEquals(sb1, sb2);
|
||||
|
||||
// Test replacement with partial string
|
||||
if (replacement.length() <= 2) {
|
||||
continue;
|
||||
}
|
||||
sb1.setLength(0);
|
||||
sb1.append(input);
|
||||
sb1.replace(startThis, endThis, replacement.substring(1, 3));
|
||||
sb2.clear();
|
||||
sb2.append(input, null);
|
||||
sb2.splice(startThis, endThis, replacement, 1, 3, null);
|
||||
assertCharSequenceEquals(sb1, sb2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertAppendCodePoint() {
|
||||
int[] cases = { 0, 1, 60, 127, 128, 0x7fff, 0x8000, 0xffff, 0x10000, 0x1f000, 0x10ffff };
|
||||
|
@ -6,7 +6,7 @@
|
||||
* others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.text;
|
||||
package com.ibm.icu.dev.text;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
@ -29,7 +29,13 @@ import com.ibm.icu.impl.Utility;
|
||||
import com.ibm.icu.lang.UCharacter;
|
||||
import com.ibm.icu.math.BigDecimal;
|
||||
import com.ibm.icu.math.MathContext;
|
||||
import com.ibm.icu.text.CurrencyPluralInfo;
|
||||
import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
import com.ibm.icu.text.NumberFormat;
|
||||
import com.ibm.icu.text.PluralRules.FixedDecimal;
|
||||
import com.ibm.icu.text.UFieldPosition;
|
||||
import com.ibm.icu.text.UTF16;
|
||||
import com.ibm.icu.text.UnicodeSet;
|
||||
import com.ibm.icu.util.Currency;
|
||||
import com.ibm.icu.util.Currency.CurrencyUsage;
|
||||
import com.ibm.icu.util.CurrencyAmount;
|
||||
@ -5217,7 +5223,10 @@ public class DecimalFormat_ICU58 extends NumberFormat {
|
||||
negSuffixPattern = posSuffixPattern;
|
||||
negPrefixPattern = PATTERN_MINUS_SIGN + posPrefixPattern;
|
||||
}
|
||||
setLocale(null, null);
|
||||
|
||||
// Can't call setLocale when not in the right package:
|
||||
//setLocale(null, null);
|
||||
|
||||
// save the pattern
|
||||
formatPattern = pattern;
|
||||
|
@ -6,10 +6,13 @@
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.text;
|
||||
package com.ibm.icu.dev.text;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import com.ibm.icu.text.DecimalFormat;
|
||||
import com.ibm.icu.text.NumberFormat;
|
||||
|
||||
/**
|
||||
* <code>DigitList</code> handles the transcoding between numeric values and
|
||||
* strings of characters. It only represents non-negative numbers. The
|
@ -1,7 +1,7 @@
|
||||
// © 2016 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
|
||||
package com.ibm.icu.text;
|
||||
package com.ibm.icu.dev.text;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
@ -18,7 +18,7 @@ from trac.resource import ResourceNotFound
|
||||
from trac.ticket.model import Ticket
|
||||
from trac.util.text import exception_to_unicode
|
||||
|
||||
okstatus = ['new','accepted','reviewing']
|
||||
okstatus = ['design','new','accepted','reviewing','reviewfeedback']
|
||||
|
||||
def run(args=None):
|
||||
"""trac check script"""
|
||||
|
Loading…
Reference in New Issue
Block a user