+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
**********************************************************************
-* Copyright (C) 2008-2010, International Business Machines
+* Copyright (C) 2008-2015, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Date Name Description
#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"
* '}'.
*/
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) {
}
* 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) {
+}
/**
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);
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.)
}
this->fInsertion = 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.