From ece6fe9ecab1f40d3a1bddb22cad8384da55c5c9 Mon Sep 17 00:00:00 2001 From: Markus Scherer Date: Wed, 30 Apr 2003 22:08:57 +0000 Subject: [PATCH] ICU-1730 add Replaceable::clone() X-SVN-Rev: 11741 --- icu4c/source/common/unicode/rep.h | 21 ++++++++++- icu4c/source/common/unicode/unistr.h | 22 ++++++++++- icu4c/source/common/unicode/urep.h | 20 +++++++++- icu4c/source/common/unistr.cpp | 14 ++++++- icu4c/source/i18n/utrans.cpp | 23 +++--------- icu4c/source/test/intltest/reptest.cpp | 49 +++++++++++++++---------- icu4c/source/test/intltest/ustrtest.cpp | 18 ++++++++- 7 files changed, 123 insertions(+), 44 deletions(-) diff --git a/icu4c/source/common/unicode/rep.h b/icu4c/source/common/unicode/rep.h index bb0c4b10505..31a6ed7b187 100644 --- a/icu4c/source/common/unicode/rep.h +++ b/icu4c/source/common/unicode/rep.h @@ -1,6 +1,6 @@ /* ************************************************************************** -* Copyright (C) 1999-2001, International Business Machines Corporation and +* Copyright (C) 1999-2003, International Business Machines Corporation and * others. All Rights Reserved. ************************************************************************** * Date Name Description @@ -178,6 +178,23 @@ public: */ virtual UBool hasMetaData() const; + /** + * Clone this object, an instance of a subclass of Replaceable. + * Clones can be used concurrently in multiple threads. + * If a subclass does not implement clone(), or if an error occurs, + * then NULL is returned. + * The clone functions in all subclasses return a pointer to a Replaceable + * because some compilers do not support covariant (same-as-this) + * return types; cast to the appropriate subclass if necessary. + * The caller must delete the clone. + * + * @return a clone of this object + * + * @see getDynamicClassID + * @draft ICU 2.6 + */ + virtual Replaceable *clone() const; + protected: /** @@ -224,7 +241,7 @@ Replaceable::char32At(int32_t offset) const { return getChar32At(offset); } -// See unistr.cpp for Replaceable::hasMetaData() +// There is no rep.cpp, see unistr.cpp for Replaceable function implementations. U_NAMESPACE_END diff --git a/icu4c/source/common/unicode/unistr.h b/icu4c/source/common/unicode/unistr.h index 9d1d705256e..7e38d0d98de 100644 --- a/icu4c/source/common/unicode/unistr.h +++ b/icu4c/source/common/unicode/unistr.h @@ -1,6 +1,6 @@ /* ********************************************************************** -* Copyright (C) 1998-2002, International Business Machines +* Copyright (C) 1998-2003, International Business Machines * Corporation and others. All Rights Reserved. ********************************************************************** * @@ -2718,9 +2718,27 @@ public: */ UnicodeString(const UnicodeString& src, int32_t srcStart, int32_t srcLength); + /** + * Clone this object, an instance of a subclass of Replaceable. + * Clones can be used concurrently in multiple threads. + * If a subclass does not implement clone(), or if an error occurs, + * then NULL is returned. + * The clone functions in all subclasses return a pointer to a Replaceable + * because some compilers do not support covariant (same-as-this) + * return types; cast to the appropriate subclass if necessary. + * The caller must delete the clone. + * + * @return a clone of this object + * + * @see Replaceable::clone + * @see getDynamicClassID + * @draft ICU 2.6 + */ + virtual Replaceable *clone() const; + /** Destructor. * @stable ICU 2.0 - */ + */ ~UnicodeString(); diff --git a/icu4c/source/common/unicode/urep.h b/icu4c/source/common/unicode/urep.h index 9465b3cc410..4e27c42be94 100644 --- a/icu4c/source/common/unicode/urep.h +++ b/icu4c/source/common/unicode/urep.h @@ -1,6 +1,6 @@ /* ****************************************************************************** -* Copyright (C) 1997-2001, International Business Machines +* Copyright (C) 1997-2003, International Business Machines * Corporation and others. All Rights Reserved. ****************************************************************************** * Date Name Description @@ -33,6 +33,7 @@ U_CDECL_BEGIN * An opaque replaceable text object. This will be manipulated only * through the caller-supplied UReplaceableFunctor struct. Related * to the C++ class Replaceable. + * This is currently only used in the Transliterator C API, see utrans.h . * @stable ICU 2.0 */ typedef void* UReplaceable; @@ -49,6 +50,9 @@ typedef struct UReplaceableCallbacks { /** * Function pointer that returns the number of UChar code units in * this text. + * + * @param rep A pointer to "this" UReplaceable object. + * @return The length of the text. * @stable ICU 2.0 */ int32_t (*length)(const UReplaceable* rep); @@ -58,6 +62,10 @@ typedef struct UReplaceableCallbacks { * offset into this text; 0 <= offset < n, where n is the value * returned by (*length)(rep). See unistr.h for a description of * charAt() vs. char32At(). + * + * @param rep A pointer to "this" UReplaceable object. + * @param offset The index at which to fetch the UChar (code unit). + * @return The UChar (code unit) at offset, or U+FFFF if the offset is out of bounds. * @stable ICU 2.0 */ UChar (*charAt)(const UReplaceable* rep, @@ -67,6 +75,10 @@ typedef struct UReplaceableCallbacks { * Function pointer that returns a UChar32 code point at the given * offset into this text. See unistr.h for a description of * charAt() vs. char32At(). + * + * @param rep A pointer to "this" UReplaceable object. + * @param offset The index at which to fetch the UChar32 (code point). + * @return The UChar32 (code point) at offset, or U+FFFF if the offset is out of bounds. * @stable ICU 2.0 */ UChar32 (*char32At)(const UReplaceable* rep, @@ -76,6 +88,8 @@ typedef struct UReplaceableCallbacks { * Function pointer that replaces text between start and limit in * this text with the given text. Attributes (out of band info) * should be retained. + * + * @param rep A pointer to "this" UReplaceable object. * @param start the starting index of the text to be replaced, * inclusive. * @param limit the ending index of the text to be replaced, @@ -95,6 +109,8 @@ typedef struct UReplaceableCallbacks { /** * Function pointer that copies the characters in the range * [start, limit) into the array dst. + * + * @param rep A pointer to "this" UReplaceable object. * @param start offset of first character which will be copied * into the array * @param limit offset immediately following the last character to @@ -114,6 +130,8 @@ typedef struct UReplaceableCallbacks { * band info) should be retained. After this call, there will be * (at least) two copies of the characters originally located at * start..limit-1. + * + * @param rep A pointer to "this" UReplaceable object. * @param start the starting index of the text to be copied, * inclusive. * @param limit the ending index of the text to be copied, diff --git a/icu4c/source/common/unistr.cpp b/icu4c/source/common/unistr.cpp index 42a34dccde8..39a4a71e2ca 100644 --- a/icu4c/source/common/unistr.cpp +++ b/icu4c/source/common/unistr.cpp @@ -1,6 +1,6 @@ /* ****************************************************************************** -* Copyright (C) 1999-2001, International Business Machines Corporation and * +* Copyright (C) 1999-2003, International Business Machines Corporation and * * others. All Rights Reserved. * ****************************************************************************** * @@ -381,6 +381,18 @@ UnicodeString::UnicodeString(const UnicodeString& that, setTo(that, srcStart, srcLength); } +// Replaceable base class clone() default implementation, does not clone +Replaceable * +Replaceable::clone() const { + return NULL; +} + +// UnicodeString overrides clone() with a real implementation +Replaceable * +UnicodeString::clone() const { + return new UnicodeString(*this); +} + //======================================== // array allocation //======================================== diff --git a/icu4c/source/i18n/utrans.cpp b/icu4c/source/i18n/utrans.cpp index 3e41abf0d72..ff1a3637067 100644 --- a/icu4c/source/i18n/utrans.cpp +++ b/icu4c/source/i18n/utrans.cpp @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 1997-2001, International Business Machines +* Copyright (C) 1997-2003, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* * Date Name Description @@ -35,13 +35,9 @@ U_NAMESPACE_BEGIN class ReplaceableGlue : public Replaceable { - UChar *buf; - int32_t bufLen; UReplaceable *rep; UReplaceableCallbacks *func; - enum { BUF_PAD = 8 }; - /** * The address of this static class variable serves as this class's ID * for ICU "poor man's RTTI". @@ -65,6 +61,8 @@ public: virtual void copy(int32_t start, int32_t limit, int32_t dest); + // virtual Replaceable *clone() const { return NULL; } same as default + /** * ICU "poor man's RTTI", returns a UClassID for the actual class. * @@ -97,13 +95,9 @@ ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable, { this->rep = replaceable; this->func = funcCallback; - buf = 0; - bufLen = 0; } -ReplaceableGlue::~ReplaceableGlue() { - uprv_free(buf); -} +ReplaceableGlue::~ReplaceableGlue() {} int32_t ReplaceableGlue::getLength() const { return (*func->length)(rep); @@ -120,14 +114,7 @@ UChar32 ReplaceableGlue::getChar32At(int32_t offset) const { void ReplaceableGlue::handleReplaceBetween(int32_t start, int32_t limit, const UnicodeString& text) { - int32_t len = text.length(); - if (buf == 0 || bufLen < len) { - uprv_free(buf); - bufLen = len + BUF_PAD; - buf = (UChar*) uprv_malloc(sizeof(UChar) * bufLen); - } - text.extract(0, len, buf); - (*func->replace)(rep, start, limit, buf, len); + (*func->replace)(rep, start, limit, text.getBuffer(), text.length()); } void ReplaceableGlue::extractBetween(int32_t start, diff --git a/icu4c/source/test/intltest/reptest.cpp b/icu4c/source/test/intltest/reptest.cpp index 367698f86c6..0d98ce99b3a 100644 --- a/icu4c/source/test/intltest/reptest.cpp +++ b/icu4c/source/test/intltest/reptest.cpp @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 2001, International Business Machines Corporation and + * Copyright (c) 2001-2003, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ /************************************************************************ @@ -59,16 +59,20 @@ public: if (i < newStyles.length()) { s.append(newStyles.charAt(i)); } else { - if (text.charAt(i) == NO_STYLE_MARK) { - s.append(NO_STYLE); - } else { - s.append((UChar)(i + 0x0031)); - } + if (text.charAt(i) == NO_STYLE_MARK) { + s.append(NO_STYLE); + } else { + s.append((UChar)(i + 0x0031)); + } } } this->styles = s; } - + + virtual Replaceable *clone() const { + return new TestReplaceable(chars, styles); + } + ~TestReplaceable(void) {} UnicodeString getStyles() { @@ -135,14 +139,14 @@ protected: // dumb implementation for now. UnicodeString s; for (int i = 0; i < newLen; ++i) { - // this doesn't really handle an embedded NO_STYLE_MARK - // in the middle of a long run of characters right -- but - // that case shouldn't happen anyway - if (getCharAt(start+i) == NO_STYLE_MARK) { - s.append(NO_STYLE); - } else { - s.append(newStyle); - } + // this doesn't really handle an embedded NO_STYLE_MARK + // in the middle of a long run of characters right -- but + // that case shouldn't happen anyway + if (getCharAt(start+i) == NO_STYLE_MARK) { + s.append(NO_STYLE); + } else { + s.append(newStyle); + } } styles.replaceBetween(start, limit, s); } @@ -179,10 +183,10 @@ void ReplaceableTest::TestReplaceableClass(void) { {0x0077, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "wxy" */ {0x0077, 0x0078, 0x0079, 0x007A, 0x0000, 0x0000}, /* "wxyz" */ {0x0077, 0x0078, 0x0079, 0x007A, 0x0075, 0x0000}, /* "wxyzu" */ - {0x0078, 0x0079, 0x007A, 0x0000, 0x0000, 0x0000}, /* "xyz" */ - {0x0077, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "wxy" */ - {0xFFFF, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "*xy" */ - {0xFFFF, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "*xy" */ + {0x0078, 0x0079, 0x007A, 0x0000, 0x0000, 0x0000}, /* "xyz" */ + {0x0077, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "wxy" */ + {0xFFFF, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "*xy" */ + {0xFFFF, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "*xy" */ }; check("Lower", rawTestArray[0], "1234"); check("Upper", rawTestArray[1], "123455"); // must map 00DF to SS @@ -215,6 +219,13 @@ void ReplaceableTest::check(const UnicodeString& transliteratorName, UParseError pe; t = Transliterator::createFromRules("test", rules, UTRANS_FORWARD, pe, status); + + // test clone() + TestReplaceable *tr2 = (TestReplaceable *)tr->clone(); + if(tr2 != NULL) { + delete tr; + tr = tr2; + } } else { t = Transliterator::createInstance(transliteratorName, UTRANS_FORWARD, status); } diff --git a/icu4c/source/test/intltest/ustrtest.cpp b/icu4c/source/test/intltest/ustrtest.cpp index 3b727d57f9a..9ad11f71ff5 100644 --- a/icu4c/source/test/intltest/ustrtest.cpp +++ b/icu4c/source/test/intltest/ustrtest.cpp @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2002, International Business Machines Corporation and + * Copyright (c) 1997-2003, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ @@ -63,12 +63,20 @@ UnicodeStringTest::TestBasicManipulation() { UnicodeString test1("Now is the time for all men to come swiftly to the aid of the party.\n"); UnicodeString expectedValue; + UnicodeString *c; + c=(UnicodeString *)test1.clone(); test1.insert(24, "good "); expectedValue = "Now is the time for all good men to come swiftly to the aid of the party.\n"; if (test1 != expectedValue) errln("insert() failed: expected \"" + expectedValue + "\"\n,got \"" + test1 + "\""); + c->insert(24, "good "); + if(*c != expectedValue) { + errln("clone()->insert() failed: expected \"" + expectedValue + "\"\n,got \"" + *c + "\""); + } + delete c; + test1.remove(41, 8); expectedValue = "Now is the time for all good men to come to the aid of the party.\n"; if (test1 != expectedValue) @@ -1117,11 +1125,19 @@ UnicodeStringTest::TestStackAllocation() if(test->length() != 2 || test->charAt(0) != 0x20ac || test->charAt(1) != 0x125) { errln("UnicodeString.setTo(readonly alias) does not alias correctly"); } + + UnicodeString *c=(UnicodeString *)test->clone(); + workingBuffer[1] = 0x109; if(test->charAt(1) != 0x109) { errln("UnicodeString.setTo(readonly alias) made a copy: did not see change in buffer"); } + if(c->length() != 2 || c->charAt(1) != 0x125) { + errln("clone(alias) did not copy the buffer"); + } + delete c; + test->setTo(TRUE, workingBuffer, -1); if(test->length() != 2 || test->charAt(0) != 0x20ac || test->charAt(1) != 0x109) { errln("UnicodeString.setTo(readonly alias, length -1) does not alias correctly");