Bug 2777924:Matcher copies the Java String it's applied to onto
the native heap.

Added RegexMatcher::refreshInputText APIs.

Change-Id: Ie8eee7d23f64fc4b213a60726c1e58af4af9484f
diff --git a/i18n/rematch.cpp b/i18n/rematch.cpp
index 92bad25..74e8fa2 100644
--- a/i18n/rematch.cpp
+++ b/i18n/rematch.cpp
@@ -1927,7 +1927,44 @@
     return *this;
 }
 
+// BEGIN android-added
+// Removed this function after Android upgrad to ICU4.6.
+//--------------------------------------------------------------------------------
+//
+//    refresh
+//
+//--------------------------------------------------------------------------------
+RegexMatcher &RegexMatcher::refreshInputText(UText *input, UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return *this;
+    }
+    if (input == NULL) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return *this;
+    }
+    if (utext_nativeLength(fInputText) != utext_nativeLength(input)) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return *this;
+    }
+    int64_t  pos = utext_getNativeIndex(fInputText);
+    //  Shallow read-only clone of the new UText into the existing input UText
+    fInputText = utext_clone(fInputText, input, FALSE, TRUE, &status);
+    if (U_FAILURE(status)) {
+        return *this;
+    }
+    utext_setNativeIndex(fInputText, pos);
 
+    if (fAltInputText != NULL) {
+        pos = utext_getNativeIndex(fAltInputText);
+        fAltInputText = utext_clone(fAltInputText, input, FALSE, TRUE, &status);
+        if (U_FAILURE(status)) {
+            return *this;
+        }
+        utext_setNativeIndex(fAltInputText, pos);
+    }
+    return *this;
+}
+// END android-added
 
 
 
diff --git a/i18n/unicode/regex.h b/i18n/unicode/regex.h
index 672f7ea..a27480b 100644
--- a/i18n/unicode/regex.h
+++ b/i18n/unicode/regex.h
@@ -1032,6 +1032,29 @@
     */
     virtual RegexMatcher &reset(UText *input);
 
+  // BEGIN android-added
+  // Removed this API after Android upgrade to ICU4.6.
+  /**
+    *  Set the subject text string upon which the regular expression is looking for matches
+    *  without changing any other aspect of the matching state.
+    *  The new and previous text strings must have the same content.
+    *
+    *  This function is intended for use in environments where ICU is operating on
+    *  strings that may move around in memory.  It provides a mechanism for notifying
+    *  ICU that the string has been relocated, and providing a new UText to access the
+    *  string in its new position.
+    *
+    *  Caution:  this function is normally used only by very specialized,
+    *  system-level code.
+    *
+    * @param input      The new (moved) text string.
+    * @param status     Receives errors detected by this function.
+    *
+    * @internal ICU 4.6
+    */
+    virtual RegexMatcher &refreshInputText(UText *input, UErrorCode &status);
+   // END android-added
+
 private:
     /**
      * Cause a compilation error if an application accidently attempts to
diff --git a/i18n/unicode/uregex.h b/i18n/unicode/uregex.h
index 0e8787d..4638ab8 100644
--- a/i18n/unicode/uregex.h
+++ b/i18n/unicode/uregex.h
@@ -395,6 +395,33 @@
                 UText              *dest,
                 UErrorCode         *status);
 
+// BEGIN android-added
+// Removed it after Android upgrade to ICU4.6.
+/**
+  *  Set the subject text string upon which the regular expression is looking for matches
+  *  without changing any other aspect of the matching state.
+  *  The new and previous text strings must have the same content.
+  *
+  *  This function is intended for use in environments where ICU is operating on
+  *  strings that may move around in memory.  It provides a mechanism for notifying
+  *  ICU that the string has been relocated, and providing a new UText to access the
+  *  string in its new position.
+  *
+  *   Caution:  this function is normally used only by very specialized
+  *             system-level code.
+  *
+  * @param regexp     The compiled regular expression.
+  * @param text       The new (moved) text string.
+  * @param status     Receives errors detected by this function.
+  *
+  * @internal ICU 4.6
+  */
+U_INTERNAL void U_EXPORT2
+uregex_refreshUText(URegularExpression *regexp,
+                    UText              *text,
+                    UErrorCode         *status);
+// END android-added
+
 /**
   *   Attempts to match the input string against the pattern.
   *   To succeed, the match must extend to the end of the string,
diff --git a/i18n/uregex.cpp b/i18n/uregex.cpp
index 37c567d..213568c 100644
--- a/i18n/uregex.cpp
+++ b/i18n/uregex.cpp
@@ -471,7 +471,7 @@
 //    uregex_getUText
 //
 //------------------------------------------------------------------------------
-U_CAPI UText * U_EXPORT2 
+U_CAPI UText * U_EXPORT2
 uregex_getUText(URegularExpression *regexp2,
                 UText              *dest,
                 UErrorCode         *status)  {
@@ -482,6 +482,25 @@
     return regexp->fMatcher->getInput(dest);
 }
 
+// BEGIN android-added
+// Removed this function after Android upgrade to ICU4.6.
+//------------------------------------------------------------------------------
+//
+//    uregex_refreshUText
+//
+//------------------------------------------------------------------------------
+U_CAPI void U_EXPORT2
+uregex_refreshUText(URegularExpression *regexp2,
+                    UText              *text,
+                    UErrorCode         *status) {
+    RegularExpression *regexp = (RegularExpression*)regexp2;
+    if (validateRE(regexp, status, FALSE) == FALSE) {
+        return;
+    }
+    regexp->fMatcher->refreshInputText(text, *status);
+}
+// END android-added
+
 
 //------------------------------------------------------------------------------
 //
diff --git a/test/cintltst/reapits.c b/test/cintltst/reapits.c
index 849720f..6b237f9 100644
--- a/test/cintltst/reapits.c
+++ b/test/cintltst/reapits.c
@@ -119,6 +119,11 @@
 static void TestRegexCAPI(void);
 static void TestBug4315(void);
 static void TestUTextAPI(void);
+/* BEGIN android-added
+   Removed this function after Android upgrade to ICU4.6.
+*/
+static void TestRefreshInput(void);
+/* END android-added */
 
 void addURegexTest(TestNode** root);
 
@@ -127,6 +132,11 @@
     addTest(root, &TestRegexCAPI, "regex/TestRegexCAPI");
     addTest(root, &TestBug4315,   "regex/TestBug4315");
     addTest(root, &TestUTextAPI,  "regex/TestUTextAPI");
+    /* BEGIN android-added
+       Removed this after Android upgrade to ICU4.6.
+    */
+    addTest(root, &TestRefreshInput, "regex/TestRefreshInput");
+    /* END android-added */
 }
 
 /*
@@ -2121,4 +2131,53 @@
     utext_close(&patternText);
 }
 
+/* BEGIN android-added
+   Removed this function after Android upgrade to ICU4.6.
+*/
+static void TestRefreshInput(void) {
+    /*
+     *  RefreshInput changes out the input of a URegularExpression without
+     *    changing anything else in the match state.  Used with Java JNI,
+     *    when Java moves the underlying string storage.   This test
+     *    runs a find() loop, moving the text after the first match.
+     *    The right number of matches should still be found.
+     */
+    UChar testStr[]  = {0x41, 0x20, 0x42, 0x20, 0x43, 0x0};  /* = "A B C"  */
+    UChar movedStr[] = {   0,    0,    0,    0,    0,   0};
+    UErrorCode status = U_ZERO_ERROR;
+    URegularExpression *re;
+    UText ut1 = UTEXT_INITIALIZER;
+    UText ut2 = UTEXT_INITIALIZER;
+
+    re = uregex_openC("[ABC]", 0, 0, &status);
+    TEST_ASSERT_SUCCESS(status);
+
+    utext_openUChars(&ut1, testStr, -1, &status);
+    TEST_ASSERT_SUCCESS(status);
+    uregex_setUText(re, &ut1, &status);
+    TEST_ASSERT_SUCCESS(status);
+
+    /* Find the first match "A" in the original string */
+    TEST_ASSERT(uregex_findNext(re, &status));
+    TEST_ASSERT(uregex_start(re, 0, &status) == 0);
+
+    /* Move the string, kill the original string.  */
+    u_strcpy(movedStr, testStr);
+    u_memset(testStr, 0, u_strlen(testStr));
+    utext_openUChars(&ut2, movedStr, -1, &status);
+    TEST_ASSERT_SUCCESS(status);
+    uregex_refreshUText(re, &ut2, &status);
+    TEST_ASSERT_SUCCESS(status);
+
+    /* Find the following two matches, now working in the moved string. */
+    TEST_ASSERT(uregex_findNext(re, &status));
+    TEST_ASSERT(uregex_start(re, 0, &status) == 2);
+    TEST_ASSERT(uregex_findNext(re, &status));
+    TEST_ASSERT(uregex_start(re, 0, &status) == 4);
+    TEST_ASSERT(FALSE == uregex_findNext(re, &status));
+
+    uregex_close(re);
+}
+/* END android-addedd */
+
 #endif   /*  !UCONFIG_NO_REGULAR_EXPRESSIONS */