1 /********************************************************************
3 * Copyright (c) 2001-2003, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /************************************************************************
7 * This test program is intended for testing Replaceable class.
9 * Date Name Description
10 * 11/28/2001 hshih Ported back from Java.
12 ************************************************************************/
14 #include "unicode/utypes.h"
16 #if !UCONFIG_NO_TRANSLITERATION
22 #include "unicode/rep.h"
25 //---------------------------------------------
27 //---------------------------------------------
30 * This is a test class that simulates styled text.
31 * It associates a style number (0..65535) with each character,
32 * and maintains that style in the normal fashion:
33 * When setting text from raw string or characters,<br>
34 * Set the styles to the style of the first character replaced.<br>
35 * If no characters are replaced, use the style of the previous character.<br>
36 * If at start, use the following character<br>
37 * Otherwise use NO_STYLE.
39 class TestReplaceable
: public Replaceable
{
43 static const UChar NO_STYLE
;
45 static const UChar NO_STYLE_MARK
;
48 * The address of this static class variable serves as this class's ID
49 * for ICU "poor man's RTTI".
51 static const char fgClassID
;
54 TestReplaceable (const UnicodeString
& text
,
55 const UnicodeString
& newStyles
) {
58 for (int i
= 0; i
< text
.length(); ++i
) {
59 if (i
< newStyles
.length()) {
60 s
.append(newStyles
.charAt(i
));
62 if (text
.charAt(i
) == NO_STYLE_MARK
) {
65 s
.append((UChar
)(i
+ 0x0031));
72 virtual Replaceable
*clone() const {
73 return new TestReplaceable(chars
, styles
);
76 ~TestReplaceable(void) {}
78 UnicodeString
getStyles() {
82 UnicodeString
toString() {
83 UnicodeString s
= chars
;
90 void extractBetween(int32_t start
, int32_t limit
, UnicodeString
& result
) const {
91 chars
.extractBetween(start
, limit
, result
);
95 * ICU "poor man's RTTI", returns a UClassID for the actual class.
99 virtual inline UClassID
getDynamicClassID() const { return getStaticClassID(); }
102 * ICU "poor man's RTTI", returns a UClassID for this class.
106 static inline UClassID
getStaticClassID() { return (UClassID
)&fgClassID
; }
109 virtual int32_t getLength() const {
110 return chars
.length();
113 virtual UChar
getCharAt(int32_t offset
) const{
114 return chars
.charAt(offset
);
117 virtual UChar32
getChar32At(int32_t offset
) const{
118 return chars
.char32At(offset
);
121 virtual void handleReplaceBetween(int32_t start
, int32_t limit
, const UnicodeString
& text
) {
123 this->extractBetween(start
, limit
, s
);
124 if (s
== text
) return; // NO ACTION!
125 this->chars
.replaceBetween(start
, limit
, text
);
126 fixStyles(start
, limit
, text
.length());
130 void fixStyles(int32_t start
, int32_t limit
, int32_t newLen
) {
131 UChar newStyle
= NO_STYLE
;
132 if (start
!= limit
&& styles
.charAt(start
) != NO_STYLE
) {
133 newStyle
= styles
.charAt(start
);
134 } else if (start
> 0 && getCharAt(start
-1) != NO_STYLE_MARK
) {
135 newStyle
= styles
.charAt(start
-1);
136 } else if (limit
< styles
.length()) {
137 newStyle
= styles
.charAt(limit
);
139 // dumb implementation for now.
141 for (int i
= 0; i
< newLen
; ++i
) {
142 // this doesn't really handle an embedded NO_STYLE_MARK
143 // in the middle of a long run of characters right -- but
144 // that case shouldn't happen anyway
145 if (getCharAt(start
+i
) == NO_STYLE_MARK
) {
151 styles
.replaceBetween(start
, limit
, s
);
154 virtual void copy(int32_t start
, int32_t limit
, int32_t dest
) {
155 chars
.copy(start
, limit
, dest
);
156 styles
.copy(start
, limit
, dest
);
160 const char TestReplaceable::fgClassID
=0;
162 const UChar
TestReplaceable::NO_STYLE
= 0x005F;
164 const UChar
TestReplaceable::NO_STYLE_MARK
= 0xFFFF;
167 ReplaceableTest::runIndexedTest(int32_t index
, UBool exec
,
168 const char* &name
, char* /*par*/) {
170 TESTCASE(0,TestReplaceableClass
);
171 default: name
= ""; break;
176 * Dummy Replaceable implementation for better API/code coverage.
178 class NoopReplaceable
: public Replaceable
{
180 virtual int32_t getLength() const {
184 virtual UChar
getCharAt(int32_t /*offset*/) const{
188 virtual UChar32
getChar32At(int32_t /*offset*/) const{
192 void extractBetween(int32_t /*start*/, int32_t /*limit*/, UnicodeString
& result
) const {
196 virtual void handleReplaceBetween(int32_t /*start*/, int32_t /*limit*/, const UnicodeString
&/*text*/) {
200 virtual void copy(int32_t /*start*/, int32_t /*limit*/, int32_t /*dest*/) {
204 virtual inline UClassID
getDynamicClassID() const { return getStaticClassID(); }
205 static inline UClassID
getStaticClassID() { return (UClassID
)&fgClassID
; }
208 static const char fgClassID
;
211 const char NoopReplaceable::fgClassID
=0;
213 void ReplaceableTest::TestReplaceableClass(void) {
214 UChar rawTestArray
[][6] = {
215 {0x0041, 0x0042, 0x0043, 0x0044, 0x0000, 0x0000}, // ABCD
216 {0x0061, 0x0062, 0x0063, 0x0064, 0x00DF, 0x0000}, // abcd\u00DF
217 {0x0061, 0x0042, 0x0043, 0x0044, 0x0000, 0x0000}, // aBCD
218 {0x0041, 0x0300, 0x0045, 0x0300, 0x0000, 0x0000}, // A\u0300E\u0300
219 {0x00C0, 0x00C8, 0x0000, 0x0000, 0x0000, 0x0000}, // \u00C0\u00C8
220 {0x0077, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "wxy" */
221 {0x0077, 0x0078, 0x0079, 0x007A, 0x0000, 0x0000}, /* "wxyz" */
222 {0x0077, 0x0078, 0x0079, 0x007A, 0x0075, 0x0000}, /* "wxyzu" */
223 {0x0078, 0x0079, 0x007A, 0x0000, 0x0000, 0x0000}, /* "xyz" */
224 {0x0077, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "wxy" */
225 {0xFFFF, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "*xy" */
226 {0xFFFF, 0x0078, 0x0079, 0x0000, 0x0000, 0x0000}, /* "*xy" */
228 check("Lower", rawTestArray
[0], "1234");
229 check("Upper", rawTestArray
[1], "123455"); // must map 00DF to SS
230 check("Title", rawTestArray
[2], "1234");
231 check("NFC", rawTestArray
[3], "13");
232 check("NFD", rawTestArray
[4], "1122");
233 check("*(x) > A $1 B", rawTestArray
[5], "11223");
234 check("*(x)(y) > A $2 B $1 C $2 D", rawTestArray
[6], "113322334");
235 check("*(x)(y)(z) > A $3 B $2 C $1 D", rawTestArray
[7], "114433225");
236 // Disabled for 2.4. TODO Revisit in 2.6 or later.
237 //check("*x > a", rawTestArray[8], "223"); // expect "123"?
238 //check("*x > a", rawTestArray[9], "113"); // expect "123"?
239 //check("*x > a", rawTestArray[10], "_33"); // expect "_23"?
240 //check("*(x) > A $1 B", rawTestArray[11], "__223");
242 // improve API/code coverage
243 NoopReplaceable noop
;
245 if((p
=noop
.clone())!=NULL
) {
246 errln("Replaceable::clone() does not return NULL");
250 if(!noop
.hasMetaData()) {
251 errln("Replaceable::hasMetaData() does not return TRUE");
254 // try to call the compiler-provided
255 // UMemory/UObject/Replaceable assignment operators
256 NoopReplaceable noop2
;
258 if((p
=noop2
.clone())!=NULL
) {
259 errln("noop2.Replaceable::clone() does not return NULL");
263 // try to call the compiler-provided
264 // UMemory/UObject/Replaceable copy constructors
265 NoopReplaceable
noop3(noop
);
266 if((p
=noop3
.clone())!=NULL
) {
267 errln("noop3.Replaceable::clone() does not return NULL");
272 void ReplaceableTest::check(const UnicodeString
& transliteratorName
,
273 const UnicodeString
& test
,
274 const UnicodeString
& shouldProduceStyles
)
276 UErrorCode status
= U_ZERO_ERROR
;
277 TestReplaceable
*tr
= new TestReplaceable(test
, "");
278 UnicodeString expectedStyles
= shouldProduceStyles
;
279 UnicodeString original
= tr
->toString();
282 if (transliteratorName
.charAt(0) == 0x2A /*'*'*/) {
283 UnicodeString
rules(transliteratorName
);
286 t
= Transliterator::createFromRules("test", rules
, UTRANS_FORWARD
,
290 TestReplaceable
*tr2
= (TestReplaceable
*)tr
->clone();
296 t
= Transliterator::createInstance(transliteratorName
, UTRANS_FORWARD
, status
);
298 if (U_FAILURE(status
)) {
299 log("FAIL: failed to create the ");
300 log(transliteratorName
);
301 errln(" transliterator.");
305 t
->transliterate(*tr
);
306 UnicodeString newStyles
= tr
->getStyles();
307 if (newStyles
!= expectedStyles
) {
308 errln("FAIL Styles: " + transliteratorName
+ "{" + original
+ "} => "
309 + tr
->toString() + "; should be {" + expectedStyles
+ "}!");
312 log(transliteratorName
);
316 logln(tr
->toString());
322 #endif /* #if !UCONFIG_NO_TRANSLITERATION */