| OLD | NEW |
| (Empty) |
| 1 /******************************************************************** | |
| 2 * COPYRIGHT: | |
| 3 * Copyright (c) 2001-2010, International Business Machines Corporation and | |
| 4 * others. All Rights Reserved. | |
| 5 ********************************************************************/ | |
| 6 /************************************************************************ | |
| 7 * This test program is intended for testing Replaceable class. | |
| 8 * | |
| 9 * Date Name Description | |
| 10 * 11/28/2001 hshih Ported back from Java. | |
| 11 * | |
| 12 ************************************************************************/ | |
| 13 | |
| 14 #include "unicode/utypes.h" | |
| 15 | |
| 16 #if !UCONFIG_NO_TRANSLITERATION | |
| 17 | |
| 18 #include "ittrans.h" | |
| 19 #include <string.h> | |
| 20 #include <stdio.h> | |
| 21 #include <stdlib.h> | |
| 22 #include "unicode/rep.h" | |
| 23 #include "reptest.h" | |
| 24 | |
| 25 //--------------------------------------------- | |
| 26 // runIndexedTest | |
| 27 //--------------------------------------------- | |
| 28 | |
| 29 /** | |
| 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.<b
r> | |
| 36 * If at start, use the following character<br> | |
| 37 * Otherwise use NO_STYLE. | |
| 38 */ | |
| 39 class TestReplaceable : public Replaceable { | |
| 40 UnicodeString chars; | |
| 41 UnicodeString styles; | |
| 42 | |
| 43 static const UChar NO_STYLE; | |
| 44 | |
| 45 static const UChar NO_STYLE_MARK; | |
| 46 | |
| 47 /** | |
| 48 * The address of this static class variable serves as this class's ID | |
| 49 * for ICU "poor man's RTTI". | |
| 50 */ | |
| 51 static const char fgClassID; | |
| 52 | |
| 53 public: | |
| 54 TestReplaceable (const UnicodeString& text, | |
| 55 const UnicodeString& newStyles) { | |
| 56 chars = text; | |
| 57 UnicodeString s; | |
| 58 for (int i = 0; i < text.length(); ++i) { | |
| 59 if (i < newStyles.length()) { | |
| 60 s.append(newStyles.charAt(i)); | |
| 61 } else { | |
| 62 if (text.charAt(i) == NO_STYLE_MARK) { | |
| 63 s.append(NO_STYLE); | |
| 64 } else { | |
| 65 s.append((UChar)(i + 0x0031)); | |
| 66 } | |
| 67 } | |
| 68 } | |
| 69 this->styles = s; | |
| 70 } | |
| 71 | |
| 72 virtual Replaceable *clone() const { | |
| 73 return new TestReplaceable(chars, styles); | |
| 74 } | |
| 75 | |
| 76 ~TestReplaceable(void) {} | |
| 77 | |
| 78 UnicodeString getStyles() { | |
| 79 return styles; | |
| 80 } | |
| 81 | |
| 82 UnicodeString toString() { | |
| 83 UnicodeString s = chars; | |
| 84 s.append("{"); | |
| 85 s.append(styles); | |
| 86 s.append("}"); | |
| 87 return s; | |
| 88 } | |
| 89 | |
| 90 void extractBetween(int32_t start, int32_t limit, UnicodeString& result) con
st { | |
| 91 chars.extractBetween(start, limit, result); | |
| 92 } | |
| 93 | |
| 94 /** | |
| 95 * ICU "poor man's RTTI", returns a UClassID for this class. | |
| 96 * | |
| 97 * @draft ICU 2.2 | |
| 98 */ | |
| 99 static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } | |
| 100 | |
| 101 /** | |
| 102 * ICU "poor man's RTTI", returns a UClassID for the actual class. | |
| 103 * | |
| 104 * @draft ICU 2.2 | |
| 105 */ | |
| 106 virtual inline UClassID getDynamicClassID() const { return getStaticClassID(
); } | |
| 107 | |
| 108 protected: | |
| 109 virtual int32_t getLength() const { | |
| 110 return chars.length(); | |
| 111 } | |
| 112 | |
| 113 virtual UChar getCharAt(int32_t offset) const{ | |
| 114 return chars.charAt(offset); | |
| 115 } | |
| 116 | |
| 117 virtual UChar32 getChar32At(int32_t offset) const{ | |
| 118 return chars.char32At(offset); | |
| 119 } | |
| 120 | |
| 121 void fixStyles(int32_t start, int32_t limit, int32_t newLen) { | |
| 122 UChar newStyle = NO_STYLE; | |
| 123 if (start != limit && styles.charAt(start) != NO_STYLE) { | |
| 124 newStyle = styles.charAt(start); | |
| 125 } else if (start > 0 && getCharAt(start-1) != NO_STYLE_MARK) { | |
| 126 newStyle = styles.charAt(start-1); | |
| 127 } else if (limit < styles.length()) { | |
| 128 newStyle = styles.charAt(limit); | |
| 129 } | |
| 130 // dumb implementation for now. | |
| 131 UnicodeString s; | |
| 132 for (int i = 0; i < newLen; ++i) { | |
| 133 // this doesn't really handle an embedded NO_STYLE_MARK | |
| 134 // in the middle of a long run of characters right -- but | |
| 135 // that case shouldn't happen anyway | |
| 136 if (getCharAt(start+i) == NO_STYLE_MARK) { | |
| 137 s.append(NO_STYLE); | |
| 138 } else { | |
| 139 s.append(newStyle); | |
| 140 } | |
| 141 } | |
| 142 styles.replaceBetween(start, limit, s); | |
| 143 } | |
| 144 | |
| 145 virtual void handleReplaceBetween(int32_t start, int32_t limit, const Unicod
eString& text) { | |
| 146 UnicodeString s; | |
| 147 this->extractBetween(start, limit, s); | |
| 148 if (s == text) return; // NO ACTION! | |
| 149 this->chars.replaceBetween(start, limit, text); | |
| 150 fixStyles(start, limit, text.length()); | |
| 151 } | |
| 152 | |
| 153 | |
| 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); | |
| 157 } | |
| 158 }; | |
| 159 | |
| 160 const char TestReplaceable::fgClassID=0; | |
| 161 | |
| 162 const UChar TestReplaceable::NO_STYLE = 0x005F; | |
| 163 | |
| 164 const UChar TestReplaceable::NO_STYLE_MARK = 0xFFFF; | |
| 165 | |
| 166 void | |
| 167 ReplaceableTest::runIndexedTest(int32_t index, UBool exec, | |
| 168 const char* &name, char* /*par*/) { | |
| 169 switch (index) { | |
| 170 TESTCASE(0,TestReplaceableClass); | |
| 171 default: name = ""; break; | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 /* | |
| 176 * Dummy Replaceable implementation for better API/code coverage. | |
| 177 */ | |
| 178 class NoopReplaceable : public Replaceable { | |
| 179 public: | |
| 180 virtual int32_t getLength() const { | |
| 181 return 0; | |
| 182 } | |
| 183 | |
| 184 virtual UChar getCharAt(int32_t /*offset*/) const{ | |
| 185 return 0xffff; | |
| 186 } | |
| 187 | |
| 188 virtual UChar32 getChar32At(int32_t /*offset*/) const{ | |
| 189 return 0xffff; | |
| 190 } | |
| 191 | |
| 192 void extractBetween(int32_t /*start*/, int32_t /*limit*/, UnicodeString& res
ult) const { | |
| 193 result.remove(); | |
| 194 } | |
| 195 | |
| 196 virtual void handleReplaceBetween(int32_t /*start*/, int32_t /*limit*/, cons
t UnicodeString &/*text*/) { | |
| 197 /* do nothing */ | |
| 198 } | |
| 199 | |
| 200 virtual void copy(int32_t /*start*/, int32_t /*limit*/, int32_t /*dest*/) { | |
| 201 /* do nothing */ | |
| 202 } | |
| 203 | |
| 204 static inline UClassID getStaticClassID() { return (UClassID)&fgClassID; } | |
| 205 virtual inline UClassID getDynamicClassID() const { return getStaticClassID(
); } | |
| 206 | |
| 207 private: | |
| 208 static const char fgClassID; | |
| 209 }; | |
| 210 | |
| 211 const char NoopReplaceable::fgClassID=0; | |
| 212 | |
| 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" */ | |
| 227 }; | |
| 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"); | |
| 241 | |
| 242 // improve API/code coverage | |
| 243 NoopReplaceable noop; | |
| 244 Replaceable *p; | |
| 245 if((p=noop.clone())!=NULL) { | |
| 246 errln("Replaceable::clone() does not return NULL"); | |
| 247 delete p; | |
| 248 } | |
| 249 | |
| 250 if(!noop.hasMetaData()) { | |
| 251 errln("Replaceable::hasMetaData() does not return TRUE"); | |
| 252 } | |
| 253 | |
| 254 // try to call the compiler-provided | |
| 255 // UMemory/UObject/Replaceable assignment operators | |
| 256 NoopReplaceable noop2; | |
| 257 noop2=noop; | |
| 258 if((p=noop2.clone())!=NULL) { | |
| 259 errln("noop2.Replaceable::clone() does not return NULL"); | |
| 260 delete p; | |
| 261 } | |
| 262 | |
| 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"); | |
| 268 delete p; | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 void ReplaceableTest::check(const UnicodeString& transliteratorName, | |
| 273 const UnicodeString& test, | |
| 274 const UnicodeString& shouldProduceStyles) | |
| 275 { | |
| 276 UErrorCode status = U_ZERO_ERROR; | |
| 277 TestReplaceable *tr = new TestReplaceable(test, ""); | |
| 278 UnicodeString expectedStyles = shouldProduceStyles; | |
| 279 UnicodeString original = tr->toString(); | |
| 280 | |
| 281 Transliterator* t; | |
| 282 if (transliteratorName.charAt(0) == 0x2A /*'*'*/) { | |
| 283 UnicodeString rules(transliteratorName); | |
| 284 rules.remove(0,1); | |
| 285 UParseError pe; | |
| 286 t = Transliterator::createFromRules("test", rules, UTRANS_FORWARD, | |
| 287 pe, status); | |
| 288 | |
| 289 // test clone() | |
| 290 TestReplaceable *tr2 = (TestReplaceable *)tr->clone(); | |
| 291 if(tr2 != NULL) { | |
| 292 delete tr; | |
| 293 tr = tr2; | |
| 294 } | |
| 295 } else { | |
| 296 t = Transliterator::createInstance(transliteratorName, UTRANS_FORWARD, s
tatus); | |
| 297 } | |
| 298 if (U_FAILURE(status)) { | |
| 299 dataerrln("FAIL: failed to create the " + transliteratorName + " transli
terator"); | |
| 300 delete tr; | |
| 301 return; | |
| 302 } | |
| 303 t->transliterate(*tr); | |
| 304 UnicodeString newStyles = tr->getStyles(); | |
| 305 if (newStyles != expectedStyles) { | |
| 306 errln("FAIL Styles: " + transliteratorName + "{" + original + "} => " | |
| 307 + tr->toString() + "; should be {" + expectedStyles + "}!"); | |
| 308 } else { | |
| 309 log("OK: "); | |
| 310 log(transliteratorName); | |
| 311 log("("); | |
| 312 log(original); | |
| 313 log(") => "); | |
| 314 logln(tr->toString()); | |
| 315 } | |
| 316 delete tr; | |
| 317 delete t; | |
| 318 } | |
| 319 | |
| 320 #endif /* #if !UCONFIG_NO_TRANSLITERATION */ | |
| OLD | NEW |