+// Try out the RuleBasedBreakIterator constructors that take RBBIDataHeader*
+// (these are protected so we access them via a local class RBBIWithProtectedFunctions).
+// This is just a sanity check, not a thorough test (e.g. we don't check that the
+// first delete actually frees rulesCopy).
+void RBBIAPITest::TestCreateFromRBBIData() {
+ // Get some handy RBBIData
+ const char *brkName = "word"; // or "sent", "line", "char", etc.
+ UErrorCode status = U_ZERO_ERROR;
+ LocalUDataMemoryPointer data(udata_open(U_ICUDATA_BRKITR, "brk", brkName, &status));
+ if ( U_SUCCESS(status) ) {
+ const RBBIDataHeader * builtRules = (const RBBIDataHeader *)udata_getMemory(data.getAlias());
+ uint32_t length = builtRules->fLength;
+ RBBIWithProtectedFunctions * brkItr;
+
+ // Try the memory-adopting constructor, need to copy the data first
+ RBBIDataHeader * rulesCopy = (RBBIDataHeader *) uprv_malloc(length);
+ if ( rulesCopy ) {
+ uprv_memcpy( rulesCopy, builtRules, length );
+
+ brkItr = new RBBIWithProtectedFunctions(rulesCopy, status);
+ if ( U_SUCCESS(status) ) {
+ delete brkItr; // this should free rulesCopy
+ } else {
+ errln("create RuleBasedBreakIterator from RBBIData (adopted): ICU Error \"%s\"\n", u_errorName(status) );
+ status = U_ZERO_ERROR;// reset for the next test
+ uprv_free( rulesCopy );
+ }
+ }
+
+ // Now try the non-adopting constructor
+ brkItr = new RBBIWithProtectedFunctions(builtRules, RBBIWithProtectedFunctions::kDontAdopt, status);
+ if ( U_SUCCESS(status) ) {
+ delete brkItr; // this should NOT attempt to free builtRules
+ if (builtRules->fLength != length) { // sanity check
+ errln("create RuleBasedBreakIterator from RBBIData (non-adopted): delete affects data\n" );
+ }
+ } else {
+ errln("create RuleBasedBreakIterator from RBBIData (non-adopted): ICU Error \"%s\"\n", u_errorName(status) );
+ }
+ }
+
+ // getBinaryRules() and RuleBasedBreakIterator(uint8_t binaryRules, ...)
+ //
+ status = U_ZERO_ERROR;
+ RuleBasedBreakIterator *rb = (RuleBasedBreakIterator *)BreakIterator::createWordInstance(Locale::getEnglish(), status);
+ if (rb == NULL || U_FAILURE(status)) {
+ dataerrln("Unable to create BreakIterator::createWordInstance (Locale::getEnglish) - %s", u_errorName(status));
+ } else {
+ uint32_t length;
+ const uint8_t *rules = rb->getBinaryRules(length);
+ RuleBasedBreakIterator *rb2 = new RuleBasedBreakIterator(rules, length, status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(*rb == *rb2);
+ UnicodeString words = "one two three ";
+ rb2->setText(words);
+ int wordCounter = 0;
+ while (rb2->next() != UBRK_DONE) {
+ wordCounter++;
+ }
+ TEST_ASSERT(wordCounter == 6);
+
+ status = U_ZERO_ERROR;
+ RuleBasedBreakIterator *rb3 = new RuleBasedBreakIterator(rules, length-1, status);
+ TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR);
+
+ delete rb;
+ delete rb2;
+ delete rb3;
+ }
+}
+
+
+void RBBIAPITest::TestRefreshInputText() {
+ /*
+ * RefreshInput changes out the input of a Break Iterator without
+ * changing anything else in the iterator's state. Used with Java JNI,
+ * when Java moves the underlying string storage. This test
+ * runs BreakIterator::next() repeatedly, moving the text in the middle of the sequence.
+ * The right set of boundaries should still be found.
+ */
+ UChar testStr[] = {0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, 0x44, 0x0}; /* = " A B C D" */
+ UChar movedStr[] = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0};
+ UErrorCode status = U_ZERO_ERROR;
+ UText ut1 = UTEXT_INITIALIZER;
+ UText ut2 = UTEXT_INITIALIZER;
+ RuleBasedBreakIterator *bi = (RuleBasedBreakIterator *)BreakIterator::createLineInstance(Locale::getEnglish(), status);
+ TEST_ASSERT_SUCCESS(status);
+
+ utext_openUChars(&ut1, testStr, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ if (U_SUCCESS(status)) {
+ bi->setText(&ut1, status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* Line boundaries will occur before each letter in the original string */
+ TEST_ASSERT(1 == bi->next());
+ TEST_ASSERT(3 == bi->next());
+
+ /* Move the string, kill the original string. */
+ u_strcpy(movedStr, testStr);
+ u_memset(testStr, 0x20, u_strlen(testStr));
+ utext_openUChars(&ut2, movedStr, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+ RuleBasedBreakIterator *returnedBI = &bi->refreshInputText(&ut2, status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(bi == returnedBI);
+
+ /* Find the following matches, now working in the moved string. */
+ TEST_ASSERT(5 == bi->next());
+ TEST_ASSERT(7 == bi->next());
+ TEST_ASSERT(8 == bi->next());
+ TEST_ASSERT(UBRK_DONE == bi->next());
+
+ utext_close(&ut1);
+ utext_close(&ut2);
+ }
+ delete bi;
+
+}
+
+