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 |