Cherry-pick: ICU-21455 Add new API ubrk_clone() and deprecate ubrk_safeClone() am: 16f37a65cd

Original change: https://android-review.googlesource.com/c/platform/external/icu/+/1581884

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I3ced8d9b5378b4d4072aa6f438dca850fbbf46cd
diff --git a/icu4c/source/common/ubrk.cpp b/icu4c/source/common/ubrk.cpp
index f8bdf5a..bb5bdd1 100644
--- a/icu4c/source/common/ubrk.cpp
+++ b/icu4c/source/common/ubrk.cpp
@@ -174,6 +174,18 @@
     return (UBreakIterator *)newBI;
 }
 
+U_CAPI UBreakIterator * U_EXPORT2
+ubrk_clone(const UBreakIterator *bi, UErrorCode *status) {
+    if (U_FAILURE(*status)) {
+        return nullptr;
+    }
+    BreakIterator *newBI = ((BreakIterator *)bi)->clone();
+    if (newBI == nullptr) {
+        *status = U_MEMORY_ALLOCATION_ERROR;
+        return nullptr;
+    }
+    return (UBreakIterator *)newBI;
+}
 
 
 U_CAPI void U_EXPORT2
diff --git a/icu4c/source/common/unicode/ubrk.h b/icu4c/source/common/unicode/ubrk.h
index 37189a8..1249b0b 100644
--- a/icu4c/source/common/unicode/ubrk.h
+++ b/icu4c/source/common/unicode/ubrk.h
@@ -296,6 +296,8 @@
                      const UChar *  text, int32_t textLength,
                      UErrorCode *   status);
 
+#ifndef U_HIDE_DEPRECATED_API
+
 /**
  * Thread safe cloning operation
  * @param bi iterator to be cloned
@@ -312,7 +314,7 @@
  * @param status to indicate whether the operation went on smoothly or there were errors
  *  An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any allocations were necessary.
  * @return pointer to the new clone
- * @stable ICU 2.0
+ * @deprecated ICU 69 Use ubrk_clone() instead.
  */
 U_CAPI UBreakIterator * U_EXPORT2
 ubrk_safeClone(
@@ -321,6 +323,23 @@
           int32_t *pBufferSize,
           UErrorCode *status);
 
+#endif /* U_HIDE_DEPRECATED_API */
+
+#ifndef U_HIDE_DRAFT_API
+
+/**
+ * Thread safe cloning operation.
+ * @param bi iterator to be cloned
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @return pointer to the new clone
+ * @draft ICU 69
+ */
+U_CAPI UBreakIterator * U_EXPORT2
+ubrk_clone(const UBreakIterator *bi,
+           UErrorCode *status);
+
+#endif  // U_HIDE_DRAFT_API
+
 #ifndef U_HIDE_DEPRECATED_API
 
 /**
diff --git a/icu4c/source/test/cintltst/cbiapts.c b/icu4c/source/test/cintltst/cbiapts.c
index c72de75..40272c8 100644
--- a/icu4c/source/test/cintltst/cbiapts.c
+++ b/icu4c/source/test/cintltst/cbiapts.c
@@ -49,6 +49,7 @@
 
 #if !UCONFIG_NO_FILE_IO
 static void TestBreakIteratorSafeClone(void);
+static void TestBreakIteratorClone(void);
 #endif
 static void TestBreakIteratorRules(void);
 static void TestBreakIteratorRuleError(void);
@@ -66,6 +67,7 @@
 #if !UCONFIG_NO_FILE_IO
     addTest(root, &TestBreakIteratorCAPI, "tstxtbd/cbiapts/TestBreakIteratorCAPI");
     addTest(root, &TestBreakIteratorSafeClone, "tstxtbd/cbiapts/TestBreakIteratorSafeClone");
+    addTest(root, &TestBreakIteratorClone, "tstxtbd/cbiapts/TestBreakIteratorClone");
     addTest(root, &TestBreakIteratorUText, "tstxtbd/cbiapts/TestBreakIteratorUText");
 #endif
     addTest(root, &TestBreakIteratorRules, "tstxtbd/cbiapts/TestBreakIteratorRules");
@@ -515,6 +517,88 @@
         ubrk_close(someIterators[i]);
     }
 }
+
+static void TestBreakIteratorClone(void)
+{
+    const UChar text[] = u"He's from Africa. Mr. Livingston, I presume? Yeah";
+    UBreakIterator * someIterators [CLONETEST_ITERATOR_COUNT];
+
+    UBreakIterator * brk;
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t start,pos;
+    int32_t i;
+
+    /*Testing ubrk_clone */
+
+    /* US & Thai - rule-based & dictionary based */
+    someIterators[0] = ubrk_open(UBRK_WORD, "en_US", text, u_strlen(text), &status);
+    if(!someIterators[0] || U_FAILURE(status)) {
+      log_data_err("Couldn't open en_US word break iterator - %s\n", u_errorName(status));
+      return;
+    }
+
+    someIterators[1] = ubrk_open(UBRK_WORD, "th_TH", text, u_strlen(text), &status);
+    if(!someIterators[1] || U_FAILURE(status)) {
+      log_data_err("Couldn't open th_TH word break iterator - %s\n", u_errorName(status));
+      return;
+    }
+
+    /* test each type of iterator */
+    for (i = 0; i < CLONETEST_ITERATOR_COUNT; i++)
+    {
+        /* error status - should return 0 & keep error the same */
+        status = U_MEMORY_ALLOCATION_ERROR;
+        if (NULL != ubrk_clone(someIterators[i], &status) || status != U_MEMORY_ALLOCATION_ERROR)
+        {
+            log_err("FAIL: Cloned Iterator failed to deal correctly with incoming error status\n");
+        }
+
+        status = U_ZERO_ERROR;
+
+        /* Do these cloned Iterators work at all - make a first & next call */
+        brk = ubrk_clone(someIterators[i], &status);
+
+        start = ubrk_first(brk);
+        if(start!=0)
+            log_err("error ubrk_start(clone) did not return 0, but %i\n", start);
+        pos=ubrk_next(brk);
+        if(pos!=4)
+            log_err("error ubrk_next(clone) did not return 4, but %i\n", pos);
+
+        ubrk_close(brk);
+
+        pos = ubrk_next(someIterators[i]);
+        if (pos != 4) {
+            log_err("error ubrk_next(iter) did not return 4, but %i\n", pos);
+        }
+
+        brk = ubrk_clone(someIterators[i], &status);
+        // The text position should be kept in the new clone.
+        start = ubrk_current(brk);
+        if (start != 4) {
+            log_err("error ubrk_current(clone) did not return 4, but %i\n", start);
+        }
+
+        pos = ubrk_next(brk);
+        if (pos != 5) {
+            log_err("error ubrk_next(clone) did not return 5, but %i\n", pos);
+        }
+        start = ubrk_current(brk);
+        if (start != 5) {
+            log_err("error ubrk_current(clone) did not return 5, but %i\n", start);
+        }
+
+        start = ubrk_current(someIterators[i]);
+        if (start != 4) {
+            log_err("error ubrk_current(iter) did not keep the same position of 4,"
+                    " but %i after advancing the position in its clone.\n", start);
+        }
+
+        ubrk_close(brk);
+
+        ubrk_close(someIterators[i]);
+    }
+}
 #endif
 
 
diff --git a/libandroidicu/include/unicode/ubrk.h b/libandroidicu/include/unicode/ubrk.h
index 37189a8..1249b0b 100644
--- a/libandroidicu/include/unicode/ubrk.h
+++ b/libandroidicu/include/unicode/ubrk.h
@@ -296,6 +296,8 @@
                      const UChar *  text, int32_t textLength,
                      UErrorCode *   status);
 
+#ifndef U_HIDE_DEPRECATED_API
+
 /**
  * Thread safe cloning operation
  * @param bi iterator to be cloned
@@ -312,7 +314,7 @@
  * @param status to indicate whether the operation went on smoothly or there were errors
  *  An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any allocations were necessary.
  * @return pointer to the new clone
- * @stable ICU 2.0
+ * @deprecated ICU 69 Use ubrk_clone() instead.
  */
 U_CAPI UBreakIterator * U_EXPORT2
 ubrk_safeClone(
@@ -321,6 +323,23 @@
           int32_t *pBufferSize,
           UErrorCode *status);
 
+#endif /* U_HIDE_DEPRECATED_API */
+
+#ifndef U_HIDE_DRAFT_API
+
+/**
+ * Thread safe cloning operation.
+ * @param bi iterator to be cloned
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @return pointer to the new clone
+ * @draft ICU 69
+ */
+U_CAPI UBreakIterator * U_EXPORT2
+ubrk_clone(const UBreakIterator *bi,
+           UErrorCode *status);
+
+#endif  // U_HIDE_DRAFT_API
+
 #ifndef U_HIDE_DEPRECATED_API
 
 /**
diff --git a/libicu/cts_headers/unicode/ubrk.h b/libicu/cts_headers/unicode/ubrk.h
index 37189a8..1249b0b 100644
--- a/libicu/cts_headers/unicode/ubrk.h
+++ b/libicu/cts_headers/unicode/ubrk.h
@@ -296,6 +296,8 @@
                      const UChar *  text, int32_t textLength,
                      UErrorCode *   status);
 
+#ifndef U_HIDE_DEPRECATED_API
+
 /**
  * Thread safe cloning operation
  * @param bi iterator to be cloned
@@ -312,7 +314,7 @@
  * @param status to indicate whether the operation went on smoothly or there were errors
  *  An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any allocations were necessary.
  * @return pointer to the new clone
- * @stable ICU 2.0
+ * @deprecated ICU 69 Use ubrk_clone() instead.
  */
 U_CAPI UBreakIterator * U_EXPORT2
 ubrk_safeClone(
@@ -321,6 +323,23 @@
           int32_t *pBufferSize,
           UErrorCode *status);
 
+#endif /* U_HIDE_DEPRECATED_API */
+
+#ifndef U_HIDE_DRAFT_API
+
+/**
+ * Thread safe cloning operation.
+ * @param bi iterator to be cloned
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @return pointer to the new clone
+ * @draft ICU 69
+ */
+U_CAPI UBreakIterator * U_EXPORT2
+ubrk_clone(const UBreakIterator *bi,
+           UErrorCode *status);
+
+#endif  // U_HIDE_DRAFT_API
+
 #ifndef U_HIDE_DEPRECATED_API
 
 /**
diff --git a/libicu/ndk_headers/unicode/ubrk.h b/libicu/ndk_headers/unicode/ubrk.h
index ce3d1f1..0b8bbf3 100644
--- a/libicu/ndk_headers/unicode/ubrk.h
+++ b/libicu/ndk_headers/unicode/ubrk.h
@@ -255,8 +255,18 @@
 
 
 
+#ifndef U_HIDE_DEPRECATED_API
 
 
+
+#endif /* U_HIDE_DEPRECATED_API */
+
+#ifndef U_HIDE_DRAFT_API
+
+
+
+#endif  // U_HIDE_DRAFT_API
+
 #ifndef U_HIDE_DEPRECATED_API
 
 /**