ICU-13513 Merging trunk to branch

X-SVN-Rev: 40819
This commit is contained in:
Shane Carr 2018-01-30 00:59:52 +00:00
commit 8d366b982d
45 changed files with 1134 additions and 608 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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
//=======================================================================

View File

@ -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"{

View File

@ -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"}

View File

@ -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

View File

@ -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);
}

View File

@ -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,

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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 ------------------------------------- ***

View File

@ -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();

View File

@ -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() {

View File

@ -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));
}
}

View File

@ -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)

View File

@ -40,6 +40,7 @@
#include "uoptions.h"
using namespace std;
using namespace icu;
class DumpFormatter {
public:

View File

@ -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

View File

@ -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;
}

View File

@ -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));
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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));

View File

@ -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();
}

View File

@ -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);
}

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:49fc6a589685cd6252d1bcfc9fd694b1ef3a298db2875eb0e655111770d0f7f6
size 12475718
oid sha256:5dc7e055663128ae9a1dae471f9a7cdaf5c28e8177b2231e8b0341c3dc8bb842
size 12475727

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9ab0aa84333a23a0e40f5641d96d4b12e0f7acc10b3ca32a98141d04af1ef59b
size 92714
oid sha256:00c43dc113177aa5a0ffda563ac2822f3dc92fdb7ae748a5938529e32a0b67d9
size 92739

View File

@ -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 {
/**

View File

@ -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 {
/**

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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 };

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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"""