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 */