]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/brktrans.cpp
ICU-59180.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / brktrans.cpp
index 5207266783960f1925f88eaccf5a420908165604..ab5a8038420b78ccd0b851cef7eed69373443b37 100644 (file)
@@ -1,6 +1,8 @@
+// © 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"
@@ -36,11 +40,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 +49,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 +73,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 +140,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.)
 }
@@ -150,21 +170,6 @@ void BreakTransliterator::setInsertion(const UnicodeString &insertion) {
     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.