ICU-4699 add Freeze to UText

X-SVN-Rev: 19197
This commit is contained in:
Andy Heninger 2006-02-17 02:16:01 +00:00
parent 449af4ef8f
commit cfd5650611
6 changed files with 139 additions and 23 deletions
icu4c/source

View file

@ -1413,7 +1413,7 @@ CharacterIteratorUT::CharacterIteratorUT(UText *ut) {
}
UErrorCode status = U_ZERO_ERROR;
fUText = utext_clone(NULL, ut, FALSE, &status);
fUText = utext_clone(NULL, ut, FALSE, TRUE, &status); // Shallow, Read-only clone.
if (fUText != NULL) {
// Set the inherited CharacterItertor fields
textLength = (int32_t)utext_nativeLength(ut);
@ -1541,7 +1541,7 @@ default:
void CharacterIteratorUT::resetTo(const UText *ut, UErrorCode *status) {
// Reset this CharacterIteratorUT to use a new UText.
fUText = utext_clone(fUText, ut, FALSE, status);
fUText = utext_clone(fUText, ut, FALSE, TRUE, status);
utext_setNativeIndex(fUText, 0);
textLength = (int32_t)utext_nativeLength(fUText);
pos = 0;
@ -1574,7 +1574,8 @@ UText *RuleBasedBreakIterator::getUText(UText *fillIn, UErrorCode &status) const
fText->getDynamicClassID() == CharacterIteratorUT::getStaticClassID())
{
CharacterIteratorUT *utcr = (CharacterIteratorUT *)fText;
result = utext_clone(fillIn, utcr->fUText, FALSE, &status);
// Shallow, Readonly clone.
result = utext_clone(fillIn, utcr->fUText, FALSE, TRUE, &status);
}
return result;
}

View file

@ -298,11 +298,16 @@ utext_openReplaceable(UText *ut, Replaceable *rep, UErrorCode *status);
* A shallow clone operation will not fail, barring truly exceptional conditions such
* as memory allocation failures.
*
* A shallow clone will preserve the utext_isWritable() state of the source object.
* Note, however, that any writing (modification) to the text is while more than one
* UText is referring to the same underlying text storage is an error with unpredictable
* results, much like modifying the underlying text directly, bypassing a
* UText wrapper.
* Shallow UText clones should be avoided if the UText functions that modify the
* text are expected to be used, either on the original or the cloned UText.
* Any such modifications can cause unpredictable behavior. Read Only
* shallow clones provide some protection against errors of this type by
* disabling text modification via the cloned UText.
*
* A shallow clone made with the readOnly parameter == FALSE will preserve the
* utext_isWritable() state of the source object. Use with caution, however.
* Write operations must be avoided while more than one UTexts exist that refer
* to the same underlying text.
*
* A UText and its clone may be safely concurrently accessed by separate threads.
* This is true for read access only with shallow clones, and for both read and
@ -316,6 +321,9 @@ utext_openReplaceable(UText *ut, Replaceable *rep, UErrorCode *status);
* be reset to become the clone.
* @param src The UText to be cloned.
* @param deep TRUE to request a deep clone, FALSE for a shallow clone.
* @param readOnly TRUE to request that the cloned UText have read only access to the
* underlying text.
* @param status Errors are returned here. For deep clones, U_UNSUPPORTED_ERROR
* will be returned if the text provider is unable to clone the
* original text.
@ -323,7 +331,7 @@ utext_openReplaceable(UText *ut, Replaceable *rep, UErrorCode *status);
* @draft ICU 3.4
*/
U_DRAFT UText * U_EXPORT2
utext_clone(UText *dest, const UText *src, UBool deep, UErrorCode *status);
utext_clone(UText *dest, const UText *src, UBool deep, UBool readOnly, UErrorCode *status);
/*****************************************************************************
@ -757,9 +765,9 @@ utext_copy(UText *ut,
* Freeze a UText. This prevents any modification to the underlying text itself
* by means of functions operating on this UText.
* <p/>
* Once frozen, a UText can not be unfrozen. The intent is to provide some
* assurance that a the text underlying a frozen UText wrapper will not
* be unexpectedly changing.
* Once frozen, a UText can not be unfrozen. The intent is to ensure
* that a the text underlying a frozen UText wrapper cannot be modified via that UText.
*
* <p/>
* Caution: freezing a UText will disable changes made via the specific
* frozen UText wrapper only; it will not have any effect on the ability to
@ -769,6 +777,7 @@ utext_copy(UText *ut,
*
* @param ut The UText to be frozen.
* @see utext_isWritable()
* @draft ICU 3.6
*/
U_DRAFT void U_EXPORT2
utext_freeze(UText *ut);

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
*
* Copyright (C) 2005, International Business Machines
* Copyright (C) 2005-2006, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
@ -259,6 +259,13 @@ utext_isWritable(const UText *ut)
}
U_DRAFT void U_EXPORT2
utext_freeze(UText *ut) {
// Zero out the WRITABLE flag.
ut->providerProperties &= ~(I32_FLAG(UTEXT_PROVIDER_WRITABLE));
}
U_DRAFT UBool U_EXPORT2
utext_hasMetaData(const UText *ut)
{
@ -305,8 +312,13 @@ utext_copy(UText *ut,
U_DRAFT UText * U_EXPORT2
utext_clone(UText *dest, const UText *src, UBool deep, UErrorCode *status) {
return src->clone(dest, src, deep, status);
utext_clone(UText *dest, const UText *src, UBool deep, UBool readOnly, UErrorCode *status) {
UText *result;
result = src->clone(dest, src, deep, status);
if (readOnly) {
utext_freeze(result);
}
return result;
}
@ -1026,6 +1038,8 @@ repTextClone(UText *dest, const UText *src, UBool deep, UErrorCode *status) {
const Replaceable *replSrc = (const Replaceable *)src->context;
dest->context = replSrc->clone();
dest->p = dest->context;
// with deep clone, the copy is writable, even when the source is not.
dest->providerProperties |= I32_FLAG(UTEXT_PROVIDER_WRITABLE);
}
return dest;
}
@ -1398,6 +1412,9 @@ unistrTextClone(UText *dest, const UText *src, UBool deep, UErrorCode *status) {
const UnicodeString *srcString = (const UnicodeString *)src->context;
dest->context = new UnicodeString(*srcString);
dest->p = dest->context;
// with deep clone, the copy is writable, even when the source is not.
dest->providerProperties |= I32_FLAG(UTEXT_PROVIDER_WRITABLE);
}
return dest;
}

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 2005, International Business Machines Corporation and
* Copyright (c) 2005-2006, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/*
@ -93,7 +93,7 @@ static void TestAPI(void) {
status = U_ZERO_ERROR;
uta = utext_openUChars(NULL, uString, -1, &status);
TEST_SUCCESS(status);
utb = utext_clone(NULL, uta, FALSE, &status);
utb = utext_clone(NULL, uta, FALSE, FALSE, &status);
TEST_SUCCESS(status);
TEST_ASSERT(utb != NULL);
TEST_ASSERT(utb != uta);

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 2005, International Business Machines Corporation and
* Copyright (c) 2005-2006, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/************************************************************************
@ -49,6 +49,8 @@ UTextTest::runIndexedTest(int32_t index, UBool exec,
if (exec) TextTest(); break;
case 1: name = "ErrorTest";
if (exec) ErrorTest(); break;
case 2: name = "FreezeTest";
if (exec) FreezeTest(); break;
default: name = ""; break;
}
}
@ -385,7 +387,7 @@ void UTextTest::TestCopyMove(const UnicodeString &us, UText *ut, UBool move,
// clone the UText. The test will be run in the cloned copy
// so that we don't alter the original.
//
targetUT = utext_clone(NULL, ut, TRUE, &status);
targetUT = utext_clone(NULL, ut, TRUE, FALSE, &status);
TEST_SUCCESS(status);
UnicodeString targetUS(us); // And copy the reference string.
@ -463,7 +465,7 @@ void UTextTest::TestReplace(
// clone the target UText. The test will be run in the cloned copy
// so that we don't alter the original.
//
targetUT = utext_clone(NULL, ut, TRUE, &status);
targetUT = utext_clone(NULL, ut, TRUE, FALSE, &status);
TEST_SUCCESS(status);
UnicodeString targetUS(us); // And copy the reference string.
@ -1091,8 +1093,94 @@ void UTextTest::ErrorTest()
utext_close(ut);
}
}
void UTextTest::FreezeTest() {
// Check isWritable() and freeze() behavior.
//
UnicodeString ustr("Hello, World.");
const char u8str[] = {char(0x31), (char)0x32, (char)0x33, 0};
const UChar u16str[] = {(UChar)0x31, (UChar)0x32, (UChar)0x44, 0};
UErrorCode status = U_ZERO_ERROR;
UText *ut = NULL;
UText *ut2 = NULL;
ut = utext_openUTF8(ut, u8str, -1, &status);
TEST_SUCCESS(status);
UBool writable = utext_isWritable(ut);
TEST_ASSERT(writable == FALSE);
utext_copy(ut, 1, 2, 0, TRUE, &status);
TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
status = U_ZERO_ERROR;
ut = utext_openUChars(ut, u16str, -1, &status);
TEST_SUCCESS(status);
writable = utext_isWritable(ut);
TEST_ASSERT(writable == FALSE);
utext_copy(ut, 1, 2, 0, TRUE, &status);
TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
status = U_ZERO_ERROR;
ut = utext_openUnicodeString(ut, &ustr, &status);
TEST_SUCCESS(status);
writable = utext_isWritable(ut);
TEST_ASSERT(writable == TRUE);
utext_freeze(ut);
writable = utext_isWritable(ut);
TEST_ASSERT(writable == FALSE);
utext_copy(ut, 1, 2, 0, TRUE, &status);
TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
status = U_ZERO_ERROR;
ut = utext_openUnicodeString(ut, &ustr, &status);
TEST_SUCCESS(status);
ut2 = utext_clone(ut2, ut, FALSE, FALSE, &status); // clone with readonly = false
TEST_SUCCESS(status);
writable = utext_isWritable(ut2);
TEST_ASSERT(writable == TRUE);
ut2 = utext_clone(ut2, ut, FALSE, TRUE, &status); // clone with readonly = true
TEST_SUCCESS(status);
writable = utext_isWritable(ut2);
TEST_ASSERT(writable == FALSE);
utext_copy(ut2, 1, 2, 0, TRUE, &status);
TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
status = U_ZERO_ERROR;
ut = utext_openConstUnicodeString(ut, (const UnicodeString *)&ustr, &status);
TEST_SUCCESS(status);
writable = utext_isWritable(ut);
TEST_ASSERT(writable == FALSE);
utext_copy(ut, 1, 2, 0, TRUE, &status);
TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
// Deep Clone of a frozen UText should re-enable writing in the copy.
status = U_ZERO_ERROR;
ut = utext_openUnicodeString(ut, &ustr, &status);
TEST_SUCCESS(status);
utext_freeze(ut);
ut2 = utext_clone(ut2, ut, TRUE, FALSE, &status); // deep clone
TEST_SUCCESS(status);
writable = utext_isWritable(ut2);
TEST_ASSERT(writable == TRUE);
// Deep clone of a frozen UText, where the base type is intrinsically non-writable,
// should NOT enable writing in the copy.
status = U_ZERO_ERROR;
ut = utext_openUChars(ut, u16str, -1, &status);
TEST_SUCCESS(status);
utext_freeze(ut);
ut2 = utext_clone(ut2, ut, TRUE, FALSE, &status); // deep clone
TEST_SUCCESS(status);
writable = utext_isWritable(ut2);
TEST_ASSERT(writable == FALSE);
// cleanup
utext_close(ut);
utext_close(ut2);
}

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 2005, International Business Machines Corporation and
* Copyright (c) 2005-2006, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/************************************************************************
@ -30,6 +30,7 @@ public:
void runIndexedTest(int32_t index, UBool exec, const char* &name, char* par=NULL);
void TextTest();
void ErrorTest();
void FreezeTest();
private:
struct m { // Map between native indices & code points.