• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /************************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 2000-2016, International Business Machines Corporation
6  * and others. All Rights Reserved.
7  ************************************************************************/
8 /************************************************************************
9 *   Date        Name        Description
10 *   1/03/2000   Madhu        Creation.
11 ************************************************************************/
12 
13 #include "unicode/utypes.h"
14 
15 #if !UCONFIG_NO_TRANSLITERATION
16 
17 #include "ittrans.h"
18 #include "transapi.h"
19 #include "unicode/utypes.h"
20 #include "unicode/translit.h"
21 #include "unicode/unifilt.h"
22 #include "cpdtrans.h"
23 #include "cmemory.h"
24 #include <string.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "unicode/rep.h"
28 #include "unicode/locid.h"
29 #include "unicode/uniset.h"
30 
getInt(UnicodeString str)31 int32_t getInt(UnicodeString str)
32 {
33     char buffer[20];
34     int len=str.length();
35     if(len>=20) {
36         len=19;
37     }
38     str.extract(0, len, buffer, "");
39     buffer[len]=0;
40     return atoi(buffer);
41 }
42 
43 //---------------------------------------------
44 // runIndexedTest
45 //---------------------------------------------
46 
47 void
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)48 TransliteratorAPITest::runIndexedTest(int32_t index, UBool exec,
49                                       const char* &name, char* /*par*/) {
50     switch (index) {
51         TESTCASE(0,TestgetInverse);
52         TESTCASE(1,TestgetID);
53         TESTCASE(2,TestGetDisplayName);
54         TESTCASE(3,TestTransliterate1);
55         TESTCASE(4,TestTransliterate2);
56         TESTCASE(5,TestTransliterate3);
57         TESTCASE(6,TestSimpleKeyboardTransliterator);
58         TESTCASE(7,TestKeyboardTransliterator1);
59         TESTCASE(8,TestKeyboardTransliterator2);
60         TESTCASE(9,TestKeyboardTransliterator3);
61         TESTCASE(10,TestGetAdoptFilter);
62         TESTCASE(11,TestClone);
63         TESTCASE(12,TestNullTransliterator);
64         TESTCASE(13,TestRegisterUnregister);
65         TESTCASE(14,TestUnicodeFunctor);
66         default: name = ""; break;
67     }
68 }
69 
70 
TestgetID()71 void TransliteratorAPITest::TestgetID() {
72     UnicodeString trans="Latin-Greek";
73     UnicodeString ID;
74     UParseError parseError;
75     UErrorCode status = U_ZERO_ERROR;
76     Transliterator* t= Transliterator::createInstance(trans, UTRANS_FORWARD, parseError, status);
77     if(t==0 || U_FAILURE(status)){
78         dataerrln("FAIL: construction of Latin-Greek -  %s",u_errorName(status));
79         return;
80     }else{
81         ID= t->getID();
82         if(ID != trans)
83             errln("FAIL: getID returned " + ID + " instead of Latin-Greek");
84         delete t;
85     }
86     int i;
87     for (i=0; i<Transliterator::countAvailableIDs(); i++){
88         status = U_ZERO_ERROR;
89         ID = (UnicodeString) Transliterator::getAvailableID(i);
90         if(ID.indexOf("Thai")>-1){
91             continue;
92         }
93         t = Transliterator::createInstance(ID, UTRANS_FORWARD, parseError, status);
94         if(t == 0){
95             errln("FAIL: " + ID);
96             continue;
97         }
98         if(ID != t->getID())
99             errln("FAIL: getID() returned " + t->getID() + " instead of " + ID);
100         delete t;
101     }
102     ID=(UnicodeString)Transliterator::getAvailableID(i);
103     if(ID != (UnicodeString)Transliterator::getAvailableID(0)){
104         errln("FAIL: calling getAvailableID(index > coundAvailableIDs) should make index=0\n");
105     }
106 
107     Transliterator* t1=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
108     Transliterator* t2=Transliterator::createInstance("Latin-Greek", UTRANS_FORWARD, parseError, status);
109     if(t1 ==0 || t2 == 0){
110         errln("FAIL: construction");
111         return;
112     }
113     Transliterator* t3=t1->clone();
114     Transliterator* t4=t2->clone();
115 
116     if(t1->getID() != t3->getID() || t2->getID() != t4->getID() ||
117        t1->getID() == t4->getID() || t2->getID() == t3->getID() ||
118        t1->getID()== t4->getID() )
119             errln("FAIL: getID or clone failed");
120 
121 
122     Transliterator* t5=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
123     if(t5 == 0)
124         errln("FAIL: construction");
125     else if(t1->getID() != t5->getID() || t5->getID() != t3->getID() || t1->getID() != t3->getID())
126         errln("FAIL: getID or clone failed");
127 
128 
129     delete t1;
130     delete t2;
131     delete t3;
132     delete t4;
133     delete t5;
134 }
135 
TestgetInverse()136 void TransliteratorAPITest::TestgetInverse() {
137      UErrorCode status = U_ZERO_ERROR;
138      UParseError parseError;
139      Transliterator* t1    = Transliterator::createInstance("Katakana-Latin", UTRANS_FORWARD, parseError, status);
140      Transliterator* invt1 = Transliterator::createInstance("Latin-Katakana", UTRANS_FORWARD, parseError, status);
141      Transliterator* t2    = Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
142      Transliterator* invt2 = Transliterator::createInstance("Devanagari-Latin", UTRANS_FORWARD, parseError, status);
143      if(t1 == 0 || invt1 == 0 || t2 == 0 || invt2 == 0) {
144          dataerrln("FAIL: in instantiation - %s", u_errorName(status));
145          return;
146      }
147 
148      Transliterator* inverse1=t1->createInverse(status);
149      Transliterator* inverse2=t2->createInverse(status);
150      if(inverse1->getID() != invt1->getID() || inverse2->getID() != invt2->getID()
151         || inverse1->getID() == invt2->getID() || inverse2->getID() == invt1->getID() )
152         errln("FAIL: getInverse() ");
153 
154      UnicodeString TransID[]={
155        "Halfwidth-Fullwidth",
156        "Fullwidth-Halfwidth",
157        "Greek-Latin" ,
158        "Latin-Greek",
159        //"Arabic-Latin", // removed in 2.0
160        //"Latin-Arabic",
161        "Katakana-Latin",
162        "Latin-Katakana",
163        //"Hebrew-Latin", // removed in 2.0
164        //"Latin-Hebrew",
165        "Cyrillic-Latin",
166        "Latin-Cyrillic",
167        "Devanagari-Latin",
168        "Latin-Devanagari",
169        "Any-Hex",
170        "Hex-Any"
171      };
172      for(uint32_t i=0; i<UPRV_LENGTHOF(TransID); i=i+2){
173          Transliterator *trans1=Transliterator::createInstance(TransID[i], UTRANS_FORWARD, parseError, status);
174          if(t1 == 0){
175            errln("FAIL: in instantiation for" + TransID[i]);
176            continue;
177          }
178          Transliterator *inver1=trans1->createInverse(status);
179          if(inver1->getID() != TransID[i+1] )
180              errln("FAIL :getInverse() for " + TransID[i] + " returned " + inver1->getID() + " instead of " + TransID[i+1]);
181          delete inver1;
182          delete trans1;
183      }
184      delete t1;
185      delete t2;
186      delete invt1;
187      delete invt2;
188      delete inverse1;
189      delete inverse2;
190 
191 }
192 
TestClone()193 void TransliteratorAPITest::TestClone(){
194     Transliterator *t1, *t2, *t3, *t4;
195     UErrorCode status = U_ZERO_ERROR;
196     UParseError parseError;
197     t1=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
198     t2=Transliterator::createInstance("Latin-Greek", UTRANS_FORWARD, parseError, status);
199     if(t1 == 0 || t2 == 0){
200         dataerrln("FAIL: construction - %s", u_errorName(status));
201         return;
202     }
203     t3=t1->clone();
204     t4=t2->clone();
205 
206     if(t1->getID() != t3->getID() || t2->getID() != t4->getID() )
207         errln("FAIL: clone or getID failed");
208     if(t1->getID()==t4->getID() || t2->getID()==t3->getID() ||  t1->getID()==t4->getID())
209         errln("FAIL: clone or getID failed");
210 
211     delete t1;
212     delete t2;
213     delete t3;
214     delete t4;
215 
216 }
217 
TestGetDisplayName()218 void TransliteratorAPITest::TestGetDisplayName() {
219     UnicodeString dispNames[]= {
220          //ID, displayName
221         //"CurlyQuotes-StraightQuotes" ,"CurlyQuotes to StraightQuotes",
222           "Any-Hex"                ,"Any to Hex Escape",
223           "Halfwidth-Fullwidth"        ,"Halfwidth to Fullwidth" ,
224           //"Latin-Arabic"               ,"Latin to Arabic"      ,
225           "Latin-Devanagari"           ,"Latin to Devanagari"  ,
226           "Greek-Latin"                ,"Greek to Latin"       ,
227           //"Arabic-Latin"               ,"Arabic to Latin"      ,
228           "Hex-Any"                ,"Hex Escape to Any",
229           "Cyrillic-Latin"             ,"Cyrillic to Latin"    ,
230           "Latin-Greek"                ,"Latin to Greek"       ,
231           "Latin-Katakana"                 ,"Latin to Katakana"        ,
232           //"Latin-Hebrew"               ,"Latin to Hebrew"      ,
233           "Katakana-Latin"                 ,"Katakana to Latin"
234       };
235     UnicodeString name="";
236     Transliterator* t;
237     UnicodeString message;
238     UErrorCode status = U_ZERO_ERROR;
239     UParseError parseError;
240 
241 #if UCONFIG_NO_FORMATTING
242     logln("Skipping, UCONFIG_NO_FORMATTING is set\n");
243     return;
244 #else
245 
246     for (uint32_t i=0; i<UPRV_LENGTHOF(dispNames); i=i+2 ) {
247         t = Transliterator::createInstance(dispNames[i+0], UTRANS_FORWARD, parseError, status);
248         if(t==0){
249              dataerrln("FAIL: construction: " + dispNames[i+0] + " - " + u_errorName(status));
250              status = U_ZERO_ERROR;
251              continue;
252         }
253         t->getDisplayName(t->getID(), name);
254         message="Display name for ID:" + t->getID();
255       //  doTest(message, name, dispNames[i+1]); //!!! This will obviously fail for any locale other than english and its children!!!
256         name="";
257         t->getDisplayName(t->getID(), Locale::getUS(), name);
258         message.remove();
259         message.append("Display name for on english locale ID:");
260         message.append(t->getID());
261     // message="Display name for on english locale ID:" + t->getID();
262         doTest(message, name, dispNames[i+1]);
263         name="";
264 
265         delete t;
266     }
267 #endif
268 
269 }
270 
TestTransliterate1()271 void TransliteratorAPITest::TestTransliterate1(){
272 
273     UnicodeString Data[]={
274          //ID, input string, transliterated string
275          "Any-Hex",         "hello",    UnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F", "") ,
276          "Hex-Any",         UnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F", ""), "hello"  ,
277          "Latin-Devanagari",CharsToUnicodeString("bha\\u0304rata"), CharsToUnicodeString("\\u092D\\u093E\\u0930\\u0924") ,
278          "Latin-Devanagari",UnicodeString("kra ksha khra gra cra dya dhya",""), CharsToUnicodeString("\\u0915\\u094D\\u0930 \\u0915\\u094D\\u0936 \\u0916\\u094D\\u0930 \\u0917\\u094D\\u0930 \\u091a\\u094D\\u0930 \\u0926\\u094D\\u092F \\u0927\\u094D\\u092F") ,
279 
280          "Devanagari-Latin",    CharsToUnicodeString("\\u092D\\u093E\\u0930\\u0924"),        CharsToUnicodeString("bh\\u0101rata"),
281      //  "Contracted-Expanded", CharsToUnicodeString("\\u00C0\\u00C1\\u0042"),               CharsToUnicodeString("\\u0041\\u0300\\u0041\\u0301\\u0042") ,
282      //  "Expanded-Contracted", CharsToUnicodeString("\\u0041\\u0300\\u0041\\u0301\\u0042"), CharsToUnicodeString("\\u00C0\\u00C1\\u0042") ,
283          //"Latin-Arabic",        "aap",                                 CharsToUnicodeString("\\u0627\\u06A4")     ,
284          //"Arabic-Latin",        CharsToUnicodeString("\\u0627\\u06A4"),                      "aap"
285     };
286 
287     UnicodeString gotResult;
288     UnicodeString temp;
289     UnicodeString message;
290     Transliterator* t;
291     logln("Testing transliterate");
292     UErrorCode status = U_ZERO_ERROR;
293     UParseError parseError;
294 
295     for(uint32_t i=0;i<UPRV_LENGTHOF(Data); i=i+3){
296         t=Transliterator::createInstance(Data[i+0], UTRANS_FORWARD, parseError, status);
297         if(t==0){
298             dataerrln("FAIL: construction: " + Data[i+0] + " Error: "  + u_errorName(status));
299             dataerrln("PreContext: " + prettify(parseError.preContext) + " PostContext: " + prettify( parseError.postContext) );
300             status = U_ZERO_ERROR;
301             continue;
302         }
303         gotResult = Data[i+1];
304         t->transliterate(gotResult);
305         message=t->getID() + "->transliterate(UnicodeString, UnicodeString) for\n\t Source:" + prettify(Data[i+1]);
306         doTest(message, gotResult, Data[i+2]);
307 
308         //doubt here
309         temp=Data[i+1];
310         t->transliterate(temp);
311         message.remove();
312         message.append(t->getID());
313         message.append("->transliterate(Replaceable) for \n\tSource:");
314         message.append(Data[i][1]);
315         doTest(message, temp, Data[i+2]);
316 
317         callEverything(t, __LINE__);
318         delete t;
319     }
320 }
321 
TestTransliterate2()322 void TransliteratorAPITest::TestTransliterate2(){
323      //testing tranliterate(String text, int start, int limit, StringBuffer result)
324    UnicodeString Data2[]={
325          //ID, input string, start, limit, transliterated string
326          "Any-Hex",         "hello! How are you?",  "0", "5", UnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F", ""), UnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F! How are you?", "") ,
327          "Any-Hex",         "hello! How are you?",  "7", "12", UnicodeString("\\u0048\\u006F\\u0077\\u0020\\u0061", ""), UnicodeString("hello! \\u0048\\u006F\\u0077\\u0020\\u0061re you?", ""),
328          "Hex-Any",         CharsToUnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F\\u0021\\u0020"), "0", "5",  "hello", "hello! "  ,
329        //  "Contracted-Expanded", CharsToUnicodeString("\\u00C0\\u00C1\\u0042"),        "1", "2",  CharsToUnicodeString("\\u0041\\u0301"), CharsToUnicodeString("\\u00C0\\u0041\\u0301\\u0042") ,
330          "Devanagari-Latin",    CharsToUnicodeString("\\u092D\\u093E\\u0930\\u0924"), "0", "1",  "bha", CharsToUnicodeString("bha\\u093E\\u0930\\u0924") ,
331          "Devanagari-Latin",    CharsToUnicodeString("\\u092D\\u093E\\u0930\\u0924"), "1", "2",  CharsToUnicodeString("\\u0314\\u0101"), CharsToUnicodeString("\\u092D\\u0314\\u0101\\u0930\\u0924")
332 
333     };
334     logln("\n   Testing transliterate(String, int, int, StringBuffer)");
335     Transliterator* t;
336     UnicodeString gotResBuf;
337     UnicodeString temp;
338     int32_t start, limit;
339     UErrorCode status = U_ZERO_ERROR;
340     UParseError parseError;
341 
342     for(uint32_t i=0; i<UPRV_LENGTHOF(Data2); i=i+6){
343         t=Transliterator::createInstance(Data2[i+0], UTRANS_FORWARD, parseError, status);
344         if(t==0){
345             dataerrln("FAIL: construction: " + prettify(Data2[i+0]) + " - " + u_errorName(status));
346             continue;
347         }
348         start=getInt(Data2[i+2]);
349         limit=getInt(Data2[i+3]);
350         Data2[i+1].extractBetween(start, limit, gotResBuf);
351         t->transliterate(gotResBuf);
352         //  errln("FAIL: calling transliterate on " + t->getID());
353         doTest(t->getID() + ".transliterate(UnicodeString, int32_t, int32_t, UnicodeString):(" + start + "," + limit + ")  for \n\t source: " + prettify(Data2[i+1]), gotResBuf, Data2[i+4]);
354 
355         temp=Data2[i+1];
356         t->transliterate(temp, start, limit);
357         doTest(t->getID() + ".transliterate(Replaceable, int32_t, int32_t, ):(" + start + "," + limit + ")  for \n\t source: " + prettify(Data2[i+1]), temp, Data2[i+5]);
358         status = U_ZERO_ERROR;
359         callEverything(t, __LINE__);
360         delete t;
361         t = NULL;
362     }
363 
364     status = U_ZERO_ERROR;
365     logln("\n   Try calling transliterate with illegal start and limit values");
366     t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
367     if(U_FAILURE(status)) {
368       errln("Error creating transliterator %s", u_errorName(status));
369       delete t;
370       return;
371     }
372     gotResBuf = temp = "try start greater than limit";
373     t->transliterate(gotResBuf, 10, 5);
374     if(gotResBuf == temp) {
375         logln("OK: start greater than limit value handled correctly");
376     } else {
377         errln("FAIL: start greater than limit value returned" + gotResBuf);
378     }
379 
380     callEverything(t, __LINE__);
381     delete t;
382 
383 }
TestTransliterate3()384 void TransliteratorAPITest::TestTransliterate3(){
385     UnicodeString rs="This is the replaceable String";
386     UnicodeString Data[] = {
387         "0",  "0",  "This is the replaceable String",
388         "2",  "3",  UnicodeString("Th\\u0069s is the replaceable String", ""),
389         "21", "23", UnicodeString("Th\\u0069s is the repl\\u0061\\u0063eable String", ""),
390         "14", "17", UnicodeString("Th\\u0069s is t\\u0068\\u0065\\u0020repl\\u0061\\u0063eable String", ""),
391     };
392     int start, limit;
393     UnicodeString message;
394     UParseError parseError;
395     UErrorCode status = U_ZERO_ERROR;
396     Transliterator *t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
397     if(U_FAILURE(status)) {
398       errln("Error creating transliterator %s", u_errorName(status));
399       delete t;
400       return;
401     }
402 
403     if(t == 0)
404         errln("FAIL : construction");
405     for(uint32_t i=0; i<UPRV_LENGTHOF(Data); i=i+3){
406         start=getInt(Data[i+0]);
407         limit=getInt(Data[i+1]);
408         t->transliterate(rs, start, limit);
409         message=t->getID() + ".transliterate(ReplaceableString, start, limit):("+start+","+limit+"):";
410         doTest(message, rs, Data[i+2]);
411     }
412     delete t;
413 }
414 
TestSimpleKeyboardTransliterator()415 void TransliteratorAPITest::TestSimpleKeyboardTransliterator(){
416     logln("simple call to transliterate");
417     UErrorCode status=U_ZERO_ERROR;
418     UParseError parseError;
419     Transliterator* t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
420     if(t == 0) {
421         UnicodeString context;
422 
423         if (parseError.preContext[0]) {
424             context += (UnicodeString)" at " + parseError.preContext;
425         }
426         if (parseError.postContext[0]) {
427             context += (UnicodeString)" | " + parseError.postContext;
428         }
429         errln((UnicodeString)"FAIL: can't create Any-Hex, " +
430               (UnicodeString)u_errorName(status) + context);
431         return;
432     }
433     UTransPosition index={19,20,20,20};
434     UnicodeString rs= "Transliterate this-''";
435     UnicodeString insertion="abc";
436     UnicodeString expected=UnicodeString("Transliterate this-'\\u0061\\u0062\\u0063'", "");
437     t->transliterate(rs, index, insertion, status);
438     if(U_FAILURE(status))
439         errln("FAIL: " + t->getID()+ ".translitere(Replaceable, int[], UnicodeString, UErrorCode)-->" + (UnicodeString)u_errorName(status));
440     t->finishTransliteration(rs, index);
441     UnicodeString message="transliterate";
442     doTest(message, rs, expected);
443 
444     logln("try calling transliterate with invalid index values");
445     UTransPosition index1[]={
446         //START, LIMIT, CURSOR
447         {10, 10, 12, 10},   //invalid since CURSOR>LIMIT valid:-START <= CURSOR <= LIMIT
448         {17, 16, 17, 17},   //invalid since START>LIMIT valid:-0<=START<=LIMIT
449         {-1, 16, 14, 16},   //invalid since START<0
450         {3,  50, 2,  50}    //invalid since LIMIT>text.length()
451     };
452     for(uint32_t i=0; i<UPRV_LENGTHOF(index1); i++){
453         status=U_ZERO_ERROR;
454         t->transliterate(rs, index1[i], insertion, status);
455         if(status == U_ILLEGAL_ARGUMENT_ERROR)
456             logln("OK: invalid index values handled correctly");
457         else
458             errln("FAIL: invalid index values didn't throw U_ILLEGAL_ARGUMENT_ERROR throw" + (UnicodeString)u_errorName(status));
459     }
460 
461     delete t;
462 }
TestKeyboardTransliterator1()463 void TransliteratorAPITest::TestKeyboardTransliterator1(){
464     UnicodeString Data[]={
465         //insertion, buffer
466         "a",   UnicodeString("\\u0061", "")                                           ,
467         "bbb", UnicodeString("\\u0061\\u0062\\u0062\\u0062", "")                      ,
468         "ca",  UnicodeString("\\u0061\\u0062\\u0062\\u0062\\u0063\\u0061", "")        ,
469         " ",   UnicodeString("\\u0061\\u0062\\u0062\\u0062\\u0063\\u0061\\u0020", "") ,
470         "",    UnicodeString("\\u0061\\u0062\\u0062\\u0062\\u0063\\u0061\\u0020", "")   ,
471 
472         "a",   UnicodeString("\\u0061", "")                                           ,
473         "b",   UnicodeString("\\u0061\\u0062", "")                                    ,
474         "z",   UnicodeString("\\u0061\\u0062\\u007A", "")                             ,
475         "",    UnicodeString("\\u0061\\u0062\\u007A", "")
476 
477     };
478     UParseError parseError;
479     UErrorCode status = U_ZERO_ERROR;
480     Transliterator* t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
481     if(U_FAILURE(status)) {
482       errln("Error creating transliterator %s", u_errorName(status));
483       delete t;
484       return;
485     }
486     //keyboardAux(t, Data);
487     UTransPosition index={0, 0, 0, 0};
488     UnicodeString s;
489     uint32_t i;
490     logln("Testing transliterate(Replaceable, int32_t, UnicodeString, UErrorCode)");
491     for (i=0; i<10; i=i+2) {
492        UnicodeString log;
493        if (Data[i+0] != "") {
494            log = s + " + " + Data[i+0] + " -> ";
495            t->transliterate(s, index, Data[i+0], status);
496            if(U_FAILURE(status)){
497                errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UnicodeString, UErrorCode)-->" + (UnicodeString)u_errorName(status));
498            continue;
499            }
500        }else {
501            log = s + " => ";
502            t->finishTransliteration(s, index);
503        }
504        // Show the start index '{' and the cursor '|'
505        displayOutput(s, Data[i+1], log, index);
506 
507     }
508 
509     s="";
510     status=U_ZERO_ERROR;
511     index.contextStart = index.contextLimit = index.start = index.limit = 0;
512     logln("Testing transliterate(Replaceable, int32_t, UChar, UErrorCode)");
513     for(i=10; i<UPRV_LENGTHOF(Data); i=i+2){
514         UnicodeString log;
515         if (Data[i+0] != "") {
516             log = s + " + " + Data[i+0] + " -> ";
517             UChar c=Data[i+0].charAt(0);
518             t->transliterate(s, index, c, status);
519             if(U_FAILURE(status)) {
520                errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UChar, UErrorCode)-->" + (UnicodeString)u_errorName(status));
521                continue;
522             }
523         } else {
524            log = s + " => ";
525            t->finishTransliteration(s, index);
526         }
527         // Show the start index '{' and the cursor '|'
528         displayOutput(s, Data[i+1], log, index);
529     }
530 
531     delete t;
532 }
533 
TestKeyboardTransliterator2()534 void TransliteratorAPITest::TestKeyboardTransliterator2(){
535     UnicodeString Data[]={
536         //insertion, buffer, index[START], index[LIMIT], index[CURSOR]
537         //data for Any-Hex
538         "abc",    UnicodeString("Initial String: add-\\u0061\\u0062\\u0063-", ""),                     "19", "20", "20",
539         "a",      UnicodeString("In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""),        "2",  "3",  "2" ,
540         "b",      UnicodeString("\\u0062In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""), "0",  "0",  "0" ,
541         "",       UnicodeString("\\u0062In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""), "0",  "0",  "0" ,
542         //data for Latin-Devanagiri
543         CharsToUnicodeString("a\\u0304"),     CharsToUnicodeString("Hindi -\\u0906-"),                            "6", "7", "6",
544         CharsToUnicodeString("ma\\u0304"),    CharsToUnicodeString("Hindi -\\u0906\\u092E\\u093E-"),              "7", "8", "7",
545         CharsToUnicodeString("ra\\u0304"),    CharsToUnicodeString("Hi\\u0930\\u093Endi -\\u0906\\u092E\\u093E-"),"1", "2", "2",
546         CharsToUnicodeString(""),       CharsToUnicodeString("Hi\\u0930\\u093Endi -\\u0906\\u092E\\u093E-"),"1", "2", "2"
547         //data for contracted-Expanded
548      //   CharsToUnicodeString("\\u00C1"), CharsToUnicodeString("Ad\\u0041\\u0301d here:"),             "1",  "2",  "1" ,
549      //   CharsToUnicodeString("\\u00C0"), CharsToUnicodeString("Ad\\u0041\\u0301d here:\\u0041\\u0300"), "11", "11", "11",
550      //   "",     CharsToUnicodeString("Ad\\u0041\\u0301d here:\\u0041\\u0300"), "11", "11", "11",
551     };
552     Transliterator *t;
553     UnicodeString rs;
554     UnicodeString dataStr;
555     logln("Testing transliterate(Replaceable, int32_t, UnicodeString, UErrorCode)");
556     UErrorCode status = U_ZERO_ERROR;
557     UParseError parseError;
558     rs="Initial String: add--";
559     t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
560     if(t == 0)
561         dataerrln("FAIL : construction - %s", u_errorName(status));
562     else {
563         keyboardAux(t, Data, rs, 0, 20);
564         delete t;
565     }
566 
567     rs="Hindi --";
568     t=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
569     if(t == 0)
570         dataerrln("FAIL : construction - %s", u_errorName(status));
571     else
572         keyboardAux(t, Data, rs, 20, 40);
573 
574 
575   //  rs="Add here:";
576  //   t=Transliterator::createInstance("Contracted-Expanded");
577  //   keyboardAux(t, Data, rs, 35, 55);
578 
579 
580     delete t;
581 }
582 
TestKeyboardTransliterator3()583 void TransliteratorAPITest::TestKeyboardTransliterator3(){
584     UnicodeString s="This is the main string";
585     UnicodeString Data[] = {
586         "0", "0", "0",  "This is the main string",
587         "1", "3", "2",  UnicodeString("Th\\u0069s is the main string", ""),
588         "20", "21", "20",  UnicodeString("Th\\u0069s is the mai\\u006E string", "")
589     };
590 
591     UErrorCode status=U_ZERO_ERROR;
592     UParseError parseError;
593     UTransPosition index={0, 0, 0, 0};
594     logln("Testing transliterate(Replaceable, int32_t, UErrorCode)");
595     Transliterator *t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
596     if(t == 0 || U_FAILURE(status)) {
597       errln("Error creating transliterator %s", u_errorName(status));
598       delete t;
599       return;
600     }
601     for(uint32_t i=0; i<UPRV_LENGTHOF(Data); i=i+4){
602         UnicodeString log;
603         index.contextStart=getInt(Data[i+0]);
604         index.contextLimit=index.limit=getInt(Data[i+1]);
605         index.start=getInt(Data[i+2]);
606         t->transliterate(s, index, status);
607         if(U_FAILURE(status)){
608            errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UErrorCode)-->" + (UnicodeString)u_errorName(status));
609            continue;
610         }
611         t->finishTransliteration(s, index);
612         log = s + " => ";
613         // Show the start index '{' and the cursor '|'
614         displayOutput(s, Data[i+3], log, index);
615     }
616 
617     delete t;
618 }
TestNullTransliterator()619 void TransliteratorAPITest::TestNullTransliterator(){
620     UErrorCode status=U_ZERO_ERROR;
621     UnicodeString s("Transliterate using null transliterator");
622     Transliterator *nullTrans=Transliterator::createInstance("Any-Null", UTRANS_FORWARD, status);
623     if (!assertSuccess(WHERE, status)) {
624         return;
625     }
626     int32_t transLimit;
627     int32_t start=0;
628     int32_t limit=s.length();
629     UnicodeString replaceable=s;
630     transLimit=nullTrans->transliterate(replaceable, start, limit);
631     if(transLimit != limit){
632         errln("ERROR: NullTransliterator->transliterate() failed");
633     }
634     doTest((UnicodeString)"nulTrans->transliterate", replaceable, s);
635     replaceable.remove();
636     replaceable.append(s);
637     UTransPosition index;
638     index.contextStart =start;
639     index.contextLimit = limit;
640     index.start = 0;
641     index.limit = limit;
642     nullTrans->finishTransliteration(replaceable, index);
643     if(index.start != limit){
644         errln("ERROR: NullTransliterator->handleTransliterate() failed");
645     }
646     doTest((UnicodeString)"NullTransliterator->handleTransliterate", replaceable, s);
647     callEverything(nullTrans, __LINE__);
648     delete nullTrans;
649 
650 
651 }
TestRegisterUnregister()652 void TransliteratorAPITest::TestRegisterUnregister(){
653 
654    UErrorCode status=U_ZERO_ERROR;
655     /* Make sure it doesn't exist */
656    if (Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status) != NULL) {
657       errln("FAIL: TestA-TestB already registered\n");
658       return;
659    }
660    /* Check inverse too
661    if (Transliterator::createInstance("TestA-TestB",
662                                       (UTransDirection)UTRANS_REVERSE) != NULL) {
663       errln("FAIL: TestA-TestB inverse already registered\n");
664       return;
665    }
666    */
667    status =U_ZERO_ERROR;
668 
669    /* Create it */
670    UParseError parseError;
671    Transliterator *t = Transliterator::createFromRules("TestA-TestB",
672                                                    "a<>b",
673                                                    UTRANS_FORWARD, parseError,
674                                                    status);
675    /* Register it */
676    Transliterator::registerInstance(t);
677 
678    /* Now check again -- should exist now*/
679    Transliterator *s = Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status);
680    if (s == NULL) {
681       errln("FAIL: TestA-TestB not registered\n");
682       return;
683    }
684    callEverything(s, __LINE__);
685    callEverything(t, __LINE__);
686    delete s;
687 
688    /* Check inverse too
689    s = Transliterator::createInstance("TestA-TestB",
690                                       (UTransDirection)UTRANS_REVERSE);
691    if (s == NULL) {
692       errln("FAIL: TestA-TestB inverse not registered\n");
693       return;
694    }
695    delete s;
696    */
697 
698    /*unregister the instance*/
699    Transliterator::unregister("TestA-TestB");
700    /* now Make sure it doesn't exist */
701    if (Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status) != NULL) {
702       errln("FAIL: TestA-TestB isn't unregistered\n");
703       return;
704    }
705 
706 }
707 
708 
709 int gTestFilter1ClassID = 0;
710 int gTestFilter2ClassID = 0;
711 int gTestFilter3ClassID = 0;
712 
713 /**
714  * Used by TestFiltering().
715  */
716 class TestFilter1 : public UnicodeFilter {
getDynamicClassID() const717     UClassID getDynamicClassID()const override { return &gTestFilter1ClassID; }
clone() const718     virtual TestFilter1* clone() const override {
719         return new TestFilter1(*this);
720     }
contains(UChar32 c) const721     virtual UBool contains(UChar32 c) const override {
722        if(c==0x63 || c==0x61 || c==0x43 || c==0x41)
723           return false;
724        else
725           return true;
726     }
727     // Stubs
toPattern(UnicodeString & result,UBool) const728     virtual UnicodeString& toPattern(UnicodeString& result,
729                                      UBool /*escapeUnprintable*/) const override {
730         return result;
731     }
matchesIndexValue(uint8_t) const732     virtual UBool matchesIndexValue(uint8_t /*v*/) const override {
733         return false;
734     }
addMatchSetTo(UnicodeSet &) const735     virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const override {}
736 };
737 class TestFilter2 : public UnicodeFilter {
getDynamicClassID() const738     UClassID getDynamicClassID() const override { return &gTestFilter2ClassID; }
clone() const739     virtual TestFilter2* clone() const override {
740         return new TestFilter2(*this);
741     }
contains(UChar32 c) const742     virtual UBool contains(UChar32 c) const override {
743         if(c==0x65 || c==0x6c)
744            return false;
745         else
746            return true;
747     }
748     // Stubs
toPattern(UnicodeString & result,UBool) const749     virtual UnicodeString& toPattern(UnicodeString& result,
750                                      UBool /*escapeUnprintable*/) const override {
751         return result;
752     }
matchesIndexValue(uint8_t) const753     virtual UBool matchesIndexValue(uint8_t /*v*/) const override {
754         return false;
755     }
addMatchSetTo(UnicodeSet &) const756     virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const override {}
757 };
758 class TestFilter3 : public UnicodeFilter {
getDynamicClassID() const759     UClassID getDynamicClassID() const override { return &gTestFilter3ClassID; }
clone() const760     virtual TestFilter3* clone() const override {
761         return new TestFilter3(*this);
762     }
contains(UChar32 c) const763     virtual UBool contains(UChar32 c) const override {
764         if(c==0x6f || c==0x77)
765            return false;
766         else
767            return true;
768     }
769     // Stubs
toPattern(UnicodeString & result,UBool) const770     virtual UnicodeString& toPattern(UnicodeString& result,
771                                      UBool /*escapeUnprintable*/) const override {
772         return result;
773     }
matchesIndexValue(uint8_t) const774     virtual UBool matchesIndexValue(uint8_t /*v*/) const override {
775         return false;
776     }
addMatchSetTo(UnicodeSet &) const777     virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const override {}
778 };
779 
780 
TestGetAdoptFilter()781 void TransliteratorAPITest::TestGetAdoptFilter(){
782     UErrorCode status = U_ZERO_ERROR;
783     UParseError parseError;
784     Transliterator *t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
785     if(t == 0 || U_FAILURE(status)) {
786         errln("Error creating transliterator %s", u_errorName(status));
787         delete t;
788         return;
789     }
790     const UnicodeFilter *u=t->getFilter();
791     if(u != NULL){
792         errln("FAIL: getFilter failed. Didn't return null when the transliterator used no filtering");
793         delete t;
794         return;
795     }
796 
797     UnicodeString got, temp, message;
798     UnicodeString data="ABCabcbbCBa";
799     temp = data;
800     t->transliterate(temp);
801     t->adoptFilter(new TestFilter1);
802 
803     got = data;
804     t->transliterate(got);
805     UnicodeString exp=UnicodeString("A\\u0042Ca\\u0062c\\u0062\\u0062C\\u0042a", "");
806     message="transliteration after adoptFilter(a,A,c,C) ";
807     doTest(message, got, exp);
808 
809     logln("Testing round trip");
810     t->adoptFilter((UnicodeFilter*)u);
811     if(t->getFilter() == NULL)
812        logln("OK: adoptFilter and getFilter round trip worked");
813     else
814        errln("FAIL: adoptFilter or getFilter round trip failed");
815 
816     got = data;
817     t->transliterate(got);
818     exp=UnicodeString("\\u0041\\u0042\\u0043\\u0061\\u0062\\u0063\\u0062\\u0062\\u0043\\u0042\\u0061", "");
819     message="transliteration after adopting null filter";
820     doTest(message, got, exp);
821     message="adoptFilter round trip";
822     doTest("adoptFilter round trip", got, temp);
823 
824     t->adoptFilter(new TestFilter2);
825     callEverything(t, __LINE__);
826     data="heelloe";
827     exp=UnicodeString("\\u0068eell\\u006Fe", "");
828     got = data;
829     t->transliterate(got);
830     message="transliteration using (e,l) filter";
831     doTest("transliteration using (e,l) filter", got, exp);
832 
833     data="are well";
834     exp=UnicodeString("\\u0061\\u0072e\\u0020\\u0077ell", "");
835     got = data;
836     t->transliterate(got);
837     doTest(message, got, exp);
838 
839     t->adoptFilter(new TestFilter3);
840     data="ho, wow!";
841     exp=UnicodeString("\\u0068o\\u002C\\u0020wow\\u0021", "");
842     got = data;
843     t->transliterate(got);
844     message="transliteration using (o,w) filter";
845     doTest("transliteration using (o,w) filter", got, exp);
846 
847     data="owl";
848     exp=UnicodeString("ow\\u006C", "");
849     got = data;
850     t->transliterate(got);
851     doTest("transliteration using (o,w) filter", got, exp);
852 
853     delete t;
854 
855 }
856 
857 
858 
keyboardAux(Transliterator * t,UnicodeString DATA[],UnicodeString & s,int32_t begin,int32_t end)859 void TransliteratorAPITest::keyboardAux(Transliterator *t, UnicodeString DATA[], UnicodeString& s, int32_t begin, int32_t end) {
860     UTransPosition index={0, 0, 0, 0};
861     UErrorCode status=U_ZERO_ERROR;
862     for (int32_t i=begin; i<end; i=i+5) {
863         UnicodeString log;
864         if (DATA[i+0] != "") {
865              log = s + " + " + DATA[i] + " -> ";
866              index.contextStart=getInt(DATA[i+2]);
867              index.contextLimit=index.limit=getInt(DATA[i+3]);
868              index.start=getInt(DATA[i+4]);
869              t->transliterate(s, index, DATA[i+0], status);
870              if(U_FAILURE(status)){
871                  errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UnicodeString, UErrorCode)-->" + (UnicodeString)u_errorName(status));
872              continue;
873              }
874            log = s + " => ";
875            t->finishTransliteration(s, index);
876         }
877          // Show the start index '{' and the cursor '|'
878       displayOutput(s, DATA[i+1], log, index);
879 
880     }
881 }
882 
displayOutput(const UnicodeString & got,const UnicodeString & expected,UnicodeString & log,UTransPosition & index)883 void TransliteratorAPITest::displayOutput(const UnicodeString& got, const UnicodeString& expected, UnicodeString& log, UTransPosition& index){
884  // Show the start index '{' and the cursor '|'
885     UnicodeString a, b, c, d, e;
886     got.extractBetween(0, index.contextStart, a);
887     got.extractBetween(index.contextStart, index.start, b);
888     got.extractBetween(index.start, index.limit, c);
889     got.extractBetween(index.limit, index.contextLimit, d);
890     got.extractBetween(index.contextLimit, got.length(), e);
891     log.append(a).
892         append((UChar)0x7b/*{*/).
893         append(b).
894         append((UChar)0x7c/*|*/).
895         append(c).
896         append((UChar)0x7c).
897         append(d).
898         append((UChar)0x7d/*}*/).
899         append(e);
900     if (got == expected)
901         logln("OK:" + prettify(log));
902     else
903         errln("FAIL: " + prettify(log)  + ", expected " + prettify(expected));
904 }
905 
906 
907 /*Internal Functions used*/
doTest(const UnicodeString & message,const UnicodeString & result,const UnicodeString & expected)908 void TransliteratorAPITest::doTest(const UnicodeString& message, const UnicodeString& result, const UnicodeString& expected){
909     if (prettify(result) == prettify(expected))
910         logln((UnicodeString)"Ok: " + prettify(message) + " passed \"" + prettify(expected) + "\"");
911     else
912         dataerrln((UnicodeString)"FAIL:" + message + " failed  Got-->" + prettify(result)+ ", Expected--> " + prettify(expected) );
913 }
914 
915 
916 //
917 //  callEverything    call all of the const (non-destructive) methods on a
918 //                    transliterator, just to verify that they don't fail in some
919 //                    destructive way.
920 //
921 #define CEASSERT(a) UPRV_BLOCK_MACRO_BEGIN { \
922     if (!(a)) { \
923         errln("FAIL at line %d from line %d: %s", __LINE__, line, #a); \
924         return; \
925     } \
926 } UPRV_BLOCK_MACRO_END
927 
callEverything(const Transliterator * tr,int line)928 void TransliteratorAPITest::callEverything(const Transliterator *tr, int line) {
929     Transliterator *clonedTR = tr->clone();
930     CEASSERT(clonedTR != NULL);
931 
932     int32_t  maxcl = tr->getMaximumContextLength();
933     CEASSERT(clonedTR->getMaximumContextLength() == maxcl);
934 
935     UnicodeString id;
936     UnicodeString clonedId;
937     id = tr->getID();
938     clonedId = clonedTR->getID();
939     CEASSERT(id == clonedId);
940 
941     const UnicodeFilter *filter = tr->getFilter();
942     const UnicodeFilter *clonedFilter = clonedTR->getFilter();
943     if (filter == NULL || clonedFilter == NULL) {
944         // If one filter is NULL they better both be NULL.
945         CEASSERT(filter == clonedFilter);
946     } else {
947         CEASSERT(filter != clonedFilter);
948     }
949 
950     UnicodeString rules;
951     UnicodeString clonedRules;
952     rules = tr->toRules(rules, false);
953     clonedRules = clonedTR->toRules(clonedRules, false);
954     CEASSERT(rules == clonedRules);
955 
956     UnicodeSet sourceSet;
957     UnicodeSet clonedSourceSet;
958     tr->getSourceSet(sourceSet);
959     clonedTR->getSourceSet(clonedSourceSet);
960     CEASSERT(clonedSourceSet == sourceSet);
961 
962     UnicodeSet targetSet;
963     UnicodeSet clonedTargetSet;
964     tr->getTargetSet(targetSet);
965     clonedTR->getTargetSet(clonedTargetSet);
966     CEASSERT(targetSet == clonedTargetSet);
967 
968     UClassID classID = tr->getDynamicClassID();
969     CEASSERT(classID == clonedTR->getDynamicClassID());
970     CEASSERT(classID != 0);
971 
972     delete clonedTR;
973 }
974 
975 static const int MyUnicodeFunctorTestClassID = 0;
976 class MyUnicodeFunctorTestClass : public UnicodeFunctor {
977 public:
clone() const978     virtual UnicodeFunctor* clone() const override {return NULL;}
getStaticClassID(void)979     static UClassID getStaticClassID(void) {return (UClassID)&MyUnicodeFunctorTestClassID;}
getDynamicClassID(void) const980     virtual UClassID getDynamicClassID(void) const override {return getStaticClassID();}
setData(const TransliterationRuleData *)981     virtual void setData(const TransliterationRuleData*) override {}
982 };
983 
TestUnicodeFunctor()984 void TransliteratorAPITest::TestUnicodeFunctor() {
985     MyUnicodeFunctorTestClass myClass;
986     if (myClass.toMatcher() != NULL) {
987         errln("FAIL: UnicodeFunctor::toMatcher did not return NULL");
988     }
989     if (myClass.toReplacer() != NULL) {
990         errln("FAIL: UnicodeFunctor::toReplacer did not return NULL");
991     }
992 }
993 
994 
995 #endif /* #if !UCONFIG_NO_TRANSLITERATION */
996