Index: source/i18n/brktrans.cpp |
diff --git a/source/i18n/brktrans.cpp b/source/i18n/brktrans.cpp |
index 5207266783960f1925f88eaccf5a420908165604..dafac399f855e390b550ddcf52593beeb86116d3 100644 |
--- a/source/i18n/brktrans.cpp |
+++ b/source/i18n/brktrans.cpp |
@@ -1,6 +1,6 @@ |
/* |
********************************************************************** |
-* Copyright (C) 2008-2010, International Business Machines |
+* Copyright (C) 2008-2015, International Business Machines |
* Corporation and others. All Rights Reserved. |
********************************************************************** |
* Date Name Description |
@@ -12,13 +12,15 @@ |
#if !UCONFIG_NO_TRANSLITERATION && !UCONFIG_NO_BREAK_ITERATION |
-#include "unicode/unifilt.h" |
+#include "unicode/brkiter.h" |
+#include "unicode/localpointer.h" |
#include "unicode/uchar.h" |
+#include "unicode/unifilt.h" |
#include "unicode/uniset.h" |
-#include "unicode/brkiter.h" |
+ |
#include "brktrans.h" |
-#include "unicode/uchar.h" |
#include "cmemory.h" |
+#include "mutex.h" |
#include "uprops.h" |
#include "uinvchar.h" |
#include "util.h" |
@@ -36,11 +38,8 @@ static const UChar SPACE = 32; // ' ' |
* '}'. |
*/ |
BreakTransliterator::BreakTransliterator(UnicodeFilter* adoptedFilter) : |
- Transliterator(UNICODE_STRING("Any-BreakInternal", 17), adoptedFilter), |
- fInsertion(SPACE) { |
- bi = NULL; |
- UErrorCode status = U_ZERO_ERROR; |
- boundaries = new UVector32(status); |
+ Transliterator(UNICODE_STRING("Any-BreakInternal", 17), adoptedFilter), |
+ cachedBI(NULL), cachedBoundaries(NULL), fInsertion(SPACE) { |
} |
@@ -48,25 +47,14 @@ BreakTransliterator::BreakTransliterator(UnicodeFilter* adoptedFilter) : |
* Destructor. |
*/ |
BreakTransliterator::~BreakTransliterator() { |
- delete bi; |
- bi = NULL; |
- delete boundaries; |
- boundaries = NULL; |
} |
/** |
* Copy constructor. |
*/ |
BreakTransliterator::BreakTransliterator(const BreakTransliterator& o) : |
- Transliterator(o) { |
- bi = NULL; |
- if (o.bi != NULL) { |
- bi = o.bi->clone(); |
- } |
- fInsertion = o.fInsertion; |
- UErrorCode status = U_ZERO_ERROR; |
- boundaries = new UVector32(status); |
- } |
+ Transliterator(o), cachedBI(NULL), cachedBoundaries(NULL), fInsertion(o.fInsertion) { |
+} |
/** |
@@ -83,9 +71,27 @@ void BreakTransliterator::handleTransliterate(Replaceable& text, UTransPosition& |
UBool isIncremental ) const { |
UErrorCode status = U_ZERO_ERROR; |
+ LocalPointer<BreakIterator> bi; |
+ LocalPointer<UVector32> boundaries; |
+ |
+ { |
+ Mutex m; |
+ BreakTransliterator *nonConstThis = const_cast<BreakTransliterator *>(this); |
+ boundaries.moveFrom(nonConstThis->cachedBoundaries); |
+ bi.moveFrom(nonConstThis->cachedBI); |
+ } |
+ if (bi.isNull()) { |
+ bi.adoptInstead(BreakIterator::createWordInstance(Locale::getEnglish(), status)); |
+ } |
+ if (boundaries.isNull()) { |
+ boundaries.adoptInstead(new UVector32(status)); |
+ } |
+ |
+ if (bi.isNull() || boundaries.isNull() || U_FAILURE(status)) { |
+ return; |
+ } |
+ |
boundaries->removeAllElements(); |
- BreakTransliterator *nonConstThis = (BreakTransliterator *)this; |
- nonConstThis->getBreakIterator(); // Lazy-create it if necessary |
UnicodeString sText = replaceableAsString(text); |
bi->setText(sText); |
bi->preceding(offsets.start); |
@@ -132,6 +138,18 @@ void BreakTransliterator::handleTransliterate(Replaceable& text, UTransPosition& |
offsets.limit += delta; |
offsets.start = isIncremental ? lastBoundary + delta : offsets.limit; |
+ // Return break iterator & boundaries vector to the cache. |
+ { |
+ Mutex m; |
+ BreakTransliterator *nonConstThis = const_cast<BreakTransliterator *>(this); |
+ if (nonConstThis->cachedBI.isNull()) { |
+ nonConstThis->cachedBI.moveFrom(bi); |
+ } |
+ if (nonConstThis->cachedBoundaries.isNull()) { |
+ nonConstThis->cachedBoundaries.moveFrom(boundaries); |
+ } |
+ } |
+ |
// TODO: do something with U_FAILURE(status); |
// (need to look at transliterators overall, not just here.) |
} |
@@ -151,21 +169,6 @@ void BreakTransliterator::setInsertion(const UnicodeString &insertion) { |
} |
// |
-// getBreakIterator Lazily create the break iterator if it does |
-// not already exist. Copied from Java, probably |
-// better to just create it in the constructor. |
-// |
-BreakIterator *BreakTransliterator::getBreakIterator() { |
- UErrorCode status = U_ZERO_ERROR; |
- if (bi == NULL) { |
- // Note: Thai breaking behavior is universal, it is not |
- // tied to the Thai locale. |
- bi = BreakIterator::createWordInstance(Locale::getEnglish(), status); |
- } |
- return bi; |
-} |
- |
-// |
// replaceableAsString Hack to let break iterators work |
// on the replaceable text from transliterators. |
// In practice, the only real Replaceable type that we |