1 /*
2 *******************************************************************************
3 * Copyright (C) 1996-2014, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 */
7 
8 package com.ibm.icu.dev.test.lang;
9 
10 import com.ibm.icu.dev.test.TestFmwk;
11 import com.ibm.icu.dev.test.UTF16Util;
12 import com.ibm.icu.impl.Utility;
13 import com.ibm.icu.lang.UCharacter;
14 import com.ibm.icu.text.ReplaceableString;
15 import com.ibm.icu.text.UTF16;
16 import com.ibm.icu.text.UTF16.StringComparator;
17 
18 /**
19 * Testing class for UTF16
20 * @author Syn Wee Quek
21 * @since feb 09 2001
22 */
23 public final class UTF16Test extends TestFmwk
24 {
25     // constructor ===================================================
26 
27     /**
28      * Constructor
29      */
UTF16Test()30     public UTF16Test()
31     {
32     }
33 
34     // public methods ================================================
35 
36     /**
37      * Testing UTF16 class methods append
38      */
TestAppend()39     public void TestAppend()
40     {
41           StringBuffer strbuff = new StringBuffer("this is a string ");
42           char array[] = new char[UCharacter.MAX_VALUE >> 2];
43           int strsize = strbuff.length();
44           int arraysize = strsize;
45 
46           if (0 != strsize) {
47             strbuff.getChars(0, strsize, array, 0);
48         }
49           for (int i = 1; i < UCharacter.MAX_VALUE; i += 100) {
50         UTF16.append(strbuff, i);
51         arraysize = UTF16.append(array, arraysize, i);
52 
53         String arraystr = new String(array, 0, arraysize);
54         if (!arraystr.equals(strbuff.toString())) {
55         errln("FAIL Comparing char array append and string append " +
56               "with 0x" + Integer.toHexString(i));
57         }
58 
59         // this is to cater for the combination of 0xDBXX 0xDC50 which
60         // forms a supplementary character
61         if (i == 0xDC51) {
62         strsize --;
63         }
64 
65         if (UTF16.countCodePoint(strbuff) != strsize + (i / 100) + 1) {
66         errln("FAIL Counting code points in string appended with " +
67               " 0x" + Integer.toHexString(i));
68         break;
69         }
70     }
71 
72     // coverage for new 1.5 - cover only so no real test
73     strbuff = new StringBuffer();
74     UTF16.appendCodePoint(strbuff, 0x10000);
75     if (strbuff.length() != 2) {
76         errln("fail appendCodePoint");
77     }
78     }
79 
80     /**
81      * Testing UTF16 class methods bounds
82      */
TestBounds()83     public void TestBounds()
84     {
85           StringBuffer strbuff =
86                         //0     12345     6     7     8     9
87         new StringBuffer("\udc000123\ud800\udc00\ud801\udc01\ud802");
88           String str = strbuff.toString();
89           char array[] = str.toCharArray();
90           int boundtype[] = {UTF16.SINGLE_CHAR_BOUNDARY,
91                UTF16.SINGLE_CHAR_BOUNDARY,
92                UTF16.SINGLE_CHAR_BOUNDARY,
93                UTF16.SINGLE_CHAR_BOUNDARY,
94                UTF16.SINGLE_CHAR_BOUNDARY,
95                UTF16.LEAD_SURROGATE_BOUNDARY,
96                UTF16.TRAIL_SURROGATE_BOUNDARY,
97                UTF16.LEAD_SURROGATE_BOUNDARY,
98                UTF16.TRAIL_SURROGATE_BOUNDARY,
99                UTF16.SINGLE_CHAR_BOUNDARY};
100           int length = str.length();
101           for (int i = 0; i < length; i ++) {
102         if (UTF16.bounds(str, i) != boundtype[i]) {
103                   errln("FAIL checking bound type at index " + i);
104         }
105         if (UTF16.bounds(strbuff, i) != boundtype[i]) {
106                   errln("FAIL checking bound type at index " + i);
107         }
108         if (UTF16.bounds(array, 0, length, i) != boundtype[i]) {
109                   errln("FAIL checking bound type at index " + i);
110         }
111           }
112           // does not straddle between supplementary character
113           int start = 4;
114           int limit = 9;
115           int subboundtype1[] = {UTF16.SINGLE_CHAR_BOUNDARY,
116                    UTF16.LEAD_SURROGATE_BOUNDARY,
117                    UTF16.TRAIL_SURROGATE_BOUNDARY,
118                    UTF16.LEAD_SURROGATE_BOUNDARY,
119                    UTF16.TRAIL_SURROGATE_BOUNDARY};
120           try {
121         UTF16.bounds(array, start, limit, -1);
122         errln("FAIL Out of bounds index in bounds should fail");
123           } catch (Exception e) {
124         // getting rid of warnings
125         System.out.print("");
126           }
127 
128           for (int i = 0; i < limit - start; i ++) {
129         if (UTF16.bounds(array, start, limit, i) != subboundtype1[i]) {
130                   errln("FAILED Subarray bounds in [" + start + ", " + limit +
131               "] expected " + subboundtype1[i] + " at offset " + i);
132         }
133           }
134 
135           // starts from the mid of a supplementary character
136           int subboundtype2[] = {UTF16.SINGLE_CHAR_BOUNDARY,
137                    UTF16.LEAD_SURROGATE_BOUNDARY,
138                    UTF16.TRAIL_SURROGATE_BOUNDARY};
139 
140           start = 6;
141           limit = 9;
142           for (int i = 0; i < limit - start; i ++) {
143         if (UTF16.bounds(array, start, limit, i) != subboundtype2[i]) {
144                   errln("FAILED Subarray bounds in [" + start + ", " + limit +
145               "] expected " + subboundtype2[i] + " at offset " + i);
146         }
147           }
148 
149           // ends in the mid of a supplementary character
150           int subboundtype3[] = {UTF16.LEAD_SURROGATE_BOUNDARY,
151                    UTF16.TRAIL_SURROGATE_BOUNDARY,
152                    UTF16.SINGLE_CHAR_BOUNDARY};
153           start = 5;
154           limit = 8;
155           for (int i = 0; i < limit - start; i ++) {
156         if (UTF16.bounds(array, start, limit, i) != subboundtype3[i]) {
157                   errln("FAILED Subarray bounds in [" + start + ", " + limit +
158               "] expected " + subboundtype3[i] + " at offset " + i);
159         }
160           }
161     }
162 
163     /**
164      * Testing UTF16 class methods charAt and charAtCodePoint
165      */
TestCharAt()166     public void TestCharAt()
167     {
168           StringBuffer strbuff =
169         new StringBuffer("12345\ud800\udc0167890\ud800\udc02");
170           if (UTF16.charAt(strbuff, 0) != '1' || UTF16.charAt(strbuff, 2) != '3'
171               || UTF16.charAt(strbuff, 5) != 0x10001 ||
172         UTF16.charAt(strbuff, 6) != 0x10001 ||
173         UTF16.charAt(strbuff, 12) != 0x10002 ||
174         UTF16.charAt(strbuff, 13) != 0x10002) {
175         errln("FAIL Getting character from string buffer error" );
176           }
177           String str = strbuff.toString();
178           if (UTF16.charAt(str, 0) != '1' || UTF16.charAt(str, 2) != '3' ||
179         UTF16.charAt(str, 5) != 0x10001 || UTF16.charAt(str, 6) != 0x10001
180         || UTF16.charAt(str, 12) != 0x10002 ||
181         UTF16.charAt(str, 13) != 0x10002)
182         {
183               errln("FAIL Getting character from string error" );
184         }
185           char array[] = str.toCharArray();
186           int start = 0;
187           int limit = str.length();
188           if (UTF16.charAt(array, start, limit, 0) != '1' ||
189         UTF16.charAt(array, start, limit, 2) != '3' ||
190         UTF16.charAt(array, start, limit, 5) != 0x10001 ||
191         UTF16.charAt(array, start, limit, 6) != 0x10001 ||
192         UTF16.charAt(array, start, limit, 12) != 0x10002 ||
193         UTF16.charAt(array, start, limit, 13) != 0x10002) {
194         errln("FAIL Getting character from array error" );
195           }
196           // check the sub array here.
197           start = 6;
198           limit = 13;
199           try {
200         UTF16.charAt(array, start, limit, -1);
201         errln("FAIL out of bounds error expected");
202           } catch (Exception e) {
203         System.out.print("");
204           }
205           try {
206         UTF16.charAt(array, start, limit, 8);
207         errln("FAIL out of bounds error expected");
208           } catch (Exception e) {
209         System.out.print("");
210           }
211           if (UTF16.charAt(array, start, limit, 0) != 0xdc01) {
212         errln("FAIL Expected result in subarray 0xdc01");
213           }
214           if (UTF16.charAt(array, start, limit, 6) != 0xd800) {
215         errln("FAIL Expected result in subarray 0xd800");
216           }
217           ReplaceableString replaceable = new ReplaceableString(str);
218           if (UTF16.charAt(replaceable, 0) != '1' ||
219               UTF16.charAt(replaceable, 2) != '3' ||
220         UTF16.charAt(replaceable, 5) != 0x10001 ||
221         UTF16.charAt(replaceable, 6) != 0x10001 ||
222         UTF16.charAt(replaceable, 12) != 0x10002 ||
223         UTF16.charAt(replaceable, 13) != 0x10002) {
224         errln("FAIL Getting character from replaceable error" );
225           }
226 
227           StringBuffer strbuffer = new StringBuffer("0xD805");
228           UTF16.charAt((CharSequence)strbuffer, 0);
229     }
230 
231     /**
232      * Testing UTF16 class methods countCodePoint
233      */
TestCountCodePoint()234     public void TestCountCodePoint()
235     {
236         StringBuffer strbuff = new StringBuffer("");
237         char         array[] = null;
238         if (UTF16.countCodePoint(strbuff) != 0 ||
239         UTF16.countCodePoint("") != 0 ||
240         UTF16.countCodePoint(array,0 ,0) != 0) {
241         errln("FAIL Counting code points for empty strings");
242         }
243 
244         strbuff = new StringBuffer("this is a string ");
245         String str = strbuff.toString();
246         array = str.toCharArray();
247         int size = str.length();
248 
249         if (UTF16.countCodePoint(array, 0, 0) != 0) {
250         errln("FAIL Counting code points for 0 offset array");
251         }
252 
253         if (UTF16.countCodePoint(str) != size ||
254         UTF16.countCodePoint(strbuff) != size ||
255         UTF16.countCodePoint(array, 0, size) != size) {
256         errln("FAIL Counting code points");
257         }
258 
259         UTF16.append(strbuff, 0x10000);
260         str = strbuff.toString();
261         array = str.toCharArray();
262         if (UTF16.countCodePoint(str) != size + 1 ||
263         UTF16.countCodePoint(strbuff) != size + 1 ||
264         UTF16.countCodePoint(array, 0, size + 1) != size + 1 ||
265         UTF16.countCodePoint(array, 0, size + 2) != size + 1) {
266         errln("FAIL Counting code points");
267         }
268         UTF16.append(strbuff, 0x61);
269         str = strbuff.toString();
270         array = str.toCharArray();
271         if (UTF16.countCodePoint(str) != size + 2 ||
272         UTF16.countCodePoint(strbuff) != size + 2 ||
273         UTF16.countCodePoint(array, 0, size + 1) != size + 1 ||
274         UTF16.countCodePoint(array, 0, size + 2) != size + 1 ||
275         UTF16.countCodePoint(array, 0, size + 3) != size + 2) {
276         errln("FAIL Counting code points");
277         }
278     }
279 
280     /**
281      * Testing UTF16 class methods delete
282      */
TestDelete()283     public void TestDelete()
284     {                                        //01234567890123456
285         StringBuffer strbuff = new StringBuffer("these are strings");
286         int size = strbuff.length();
287         char array[] = strbuff.toString().toCharArray();
288 
289         UTF16.delete(strbuff, 3);
290         UTF16.delete(strbuff, 3);
291         UTF16.delete(strbuff, 3);
292         UTF16.delete(strbuff, 3);
293         UTF16.delete(strbuff, 3);
294         UTF16.delete(strbuff, 3);
295         try {
296         UTF16.delete(strbuff, strbuff.length());
297         errln("FAIL deleting out of bounds character should fail");
298         } catch (Exception e) {
299         System.out.print("");
300         }
301         UTF16.delete(strbuff, strbuff.length() - 1);
302         if (!strbuff.toString().equals("the string")) {
303         errln("FAIL expected result after deleting characters is " +
304           "\"the string\"");
305         }
306 
307         size = UTF16.delete(array, size, 3);
308         size = UTF16.delete(array, size, 3);
309         size = UTF16.delete(array, size, 3);
310         size = UTF16.delete(array, size, 3);
311         size = UTF16.delete(array, size, 3);
312         size = UTF16.delete(array, size, 3);
313         try {
314         UTF16.delete(array, size, size);
315         errln("FAIL deleting out of bounds character should fail");
316         } catch (Exception e) {
317         System.out.print("");
318         }
319         size = UTF16.delete(array, size, size - 1);
320         String str = new String(array, 0, size);
321         if (!str.equals("the string")) {
322         errln("FAIL expected result after deleting characters is " +
323           "\"the string\"");
324         }
325     //012345678     9     01     2      3     4
326         strbuff = new StringBuffer("string: \ud800\udc00 \ud801\udc01 \ud801\udc01");
327         size = strbuff.length();
328         array = strbuff.toString().toCharArray();
329 
330         UTF16.delete(strbuff, 8);
331         UTF16.delete(strbuff, 8);
332         UTF16.delete(strbuff, 9);
333         UTF16.delete(strbuff, 8);
334         UTF16.delete(strbuff, 9);
335         UTF16.delete(strbuff, 6);
336         UTF16.delete(strbuff, 6);
337         if (!strbuff.toString().equals("string")) {
338         errln("FAIL expected result after deleting characters is \"string\"");
339         }
340 
341         size = UTF16.delete(array, size, 8);
342         size = UTF16.delete(array, size, 8);
343         size = UTF16.delete(array, size, 9);
344         size = UTF16.delete(array, size, 8);
345         size = UTF16.delete(array, size, 9);
346         size = UTF16.delete(array, size, 6);
347         size = UTF16.delete(array, size, 6);
348         str = new String(array, 0, size);
349         if (!str.equals("string")) {
350         errln("FAIL expected result after deleting characters is \"string\"");
351         }
352     }
353 
354     /**
355      * Testing findOffsetFromCodePoint and findCodePointOffset
356      */
TestfindOffset()357     public void TestfindOffset()
358     {
359         // jitterbug 47
360         String str = "a\uD800\uDC00b";
361         StringBuffer strbuff = new StringBuffer(str);
362         char array[] = str.toCharArray();
363         int limit = str.length();
364         if (UTF16.findCodePointOffset(str, 0) != 0 ||
365         UTF16.findOffsetFromCodePoint(str, 0) != 0 ||
366         UTF16.findCodePointOffset(strbuff, 0) != 0 ||
367         UTF16.findOffsetFromCodePoint(strbuff, 0) != 0 ||
368         UTF16.findCodePointOffset(array, 0, limit, 0) != 0 ||
369         UTF16.findOffsetFromCodePoint(array, 0, limit, 0) != 0) {
370         errln("FAIL Getting the first codepoint offset to a string with " +
371           "supplementary characters");
372         }
373         if (UTF16.findCodePointOffset(str, 1) != 1 ||
374         UTF16.findOffsetFromCodePoint(str, 1) != 1 ||
375         UTF16.findCodePointOffset(strbuff, 1) != 1 ||
376         UTF16.findOffsetFromCodePoint(strbuff, 1) != 1 ||
377         UTF16.findCodePointOffset(array, 0, limit, 1) != 1 ||
378         UTF16.findOffsetFromCodePoint(array, 0, limit, 1) != 1) {
379         errln("FAIL Getting the second codepoint offset to a string with " +
380           "supplementary characters");
381         }
382         if (UTF16.findCodePointOffset(str, 2) != 1 ||
383         UTF16.findOffsetFromCodePoint(str, 2) != 3 ||
384         UTF16.findCodePointOffset(strbuff, 2) != 1 ||
385         UTF16.findOffsetFromCodePoint(strbuff, 2) != 3 ||
386         UTF16.findCodePointOffset(array, 0, limit, 2) != 1 ||
387         UTF16.findOffsetFromCodePoint(array, 0, limit, 2) != 3) {
388         errln("FAIL Getting the third codepoint offset to a string with " +
389           "supplementary characters");
390         }
391         if (UTF16.findCodePointOffset(str, 3) != 2 ||
392         UTF16.findOffsetFromCodePoint(str, 3) != 4 ||
393         UTF16.findCodePointOffset(strbuff, 3) != 2 ||
394         UTF16.findOffsetFromCodePoint(strbuff, 3) != 4 ||
395         UTF16.findCodePointOffset(array, 0, limit, 3) != 2 ||
396         UTF16.findOffsetFromCodePoint(array, 0, limit, 3) != 4) {
397         errln("FAIL Getting the last codepoint offset to a string with " +
398           "supplementary characters");
399         }
400         if (UTF16.findCodePointOffset(str, 4) != 3 ||
401         UTF16.findCodePointOffset(strbuff, 4) != 3 ||
402         UTF16.findCodePointOffset(array, 0, limit, 4) != 3) {
403         errln("FAIL Getting the length offset to a string with " +
404           "supplementary characters");
405         }
406         try {
407         UTF16.findCodePointOffset(str, 5);
408         errln("FAIL Getting the a non-existence codepoint to a string " +
409           "with supplementary characters");
410         } catch (Exception e) {
411         // this is a success
412         logln("Passed out of bounds codepoint offset");
413         }
414         try {
415         UTF16.findOffsetFromCodePoint(str, 4);
416         errln("FAIL Getting the a non-existence codepoint to a string " +
417           "with supplementary characters");
418         } catch (Exception e) {
419         // this is a success
420         logln("Passed out of bounds codepoint offset");
421         }
422         try {
423         UTF16.findCodePointOffset(strbuff, 5);
424         errln("FAIL Getting the a non-existence codepoint to a string " +
425           "with supplementary characters");
426         } catch (Exception e) {
427         // this is a success
428         logln("Passed out of bounds codepoint offset");
429         }
430         try {
431         UTF16.findOffsetFromCodePoint(strbuff, 4);
432         errln("FAIL Getting the a non-existence codepoint to a string " +
433           "with supplementary characters");
434         } catch (Exception e) {
435         // this is a success
436         logln("Passed out of bounds codepoint offset");
437         }
438         try {
439         UTF16.findCodePointOffset(array, 0, limit, 5);
440         errln("FAIL Getting the a non-existence codepoint to a string " +
441           "with supplementary characters");
442         } catch (Exception e) {
443         // this is a success
444         logln("Passed out of bounds codepoint offset");
445         }
446         try {
447         UTF16.findOffsetFromCodePoint(array, 0, limit, 4);
448         errln("FAIL Getting the a non-existence codepoint to a string " +
449           "with supplementary characters");
450         } catch (Exception e) {
451         // this is a success
452         logln("Passed out of bounds codepoint offset");
453         }
454 
455         if (UTF16.findCodePointOffset(array, 1, 3, 0) != 0 ||
456         UTF16.findOffsetFromCodePoint(array, 1, 3, 0) != 0 ||
457         UTF16.findCodePointOffset(array, 1, 3, 1) != 0 ||
458         UTF16.findCodePointOffset(array, 1, 3, 2) != 1 ||
459         UTF16.findOffsetFromCodePoint(array, 1, 3, 1) != 2) {
460         errln("FAIL Getting valid codepoint offset in sub array");
461         }
462     }
463 
464     /**
465      * Testing UTF16 class methods getCharCount, *Surrogate
466      */
TestGetCharCountSurrogate()467     public void TestGetCharCountSurrogate()
468     {
469         if (UTF16.getCharCount(0x61) != 1 ||
470         UTF16.getCharCount(0x10000) != 2) {
471         errln("FAIL getCharCount result failure");
472         }
473         if (UTF16.getLeadSurrogate(0x61) != 0 ||
474         UTF16.getTrailSurrogate(0x61) != 0x61 ||
475         UTF16.isLeadSurrogate((char)0x61) ||
476         UTF16.isTrailSurrogate((char)0x61) ||
477         UTF16.getLeadSurrogate(0x10000) != 0xd800 ||
478         UTF16.getTrailSurrogate(0x10000) != 0xdc00 ||
479         UTF16.isLeadSurrogate((char)0xd800) != true ||
480         UTF16.isTrailSurrogate((char)0xd800) ||
481         UTF16.isLeadSurrogate((char)0xdc00) ||
482         UTF16.isTrailSurrogate((char)0xdc00) != true) {
483         errln("FAIL *Surrogate result failure");
484         }
485 
486         if (UTF16.isSurrogate((char)0x61) || !UTF16.isSurrogate((char)0xd800)
487             || !UTF16.isSurrogate((char)0xdc00)) {
488         errln("FAIL isSurrogate result failure");
489         }
490     }
491 
492     /**
493      * Testing UTF16 class method insert
494      */
TestInsert()495     public void TestInsert()
496     {
497         StringBuffer strbuff = new StringBuffer("0123456789");
498         char array[] = new char[128];
499         int srcEnd = strbuff.length();
500         if (0 != srcEnd) {
501             strbuff.getChars(0, srcEnd, array, 0);
502         }
503         int length = 10;
504         UTF16.insert(strbuff, 5, 't');
505         UTF16.insert(strbuff, 5, 's');
506         UTF16.insert(strbuff, 5, 'e');
507         UTF16.insert(strbuff, 5, 't');
508         if (!(strbuff.toString().equals("01234test56789"))) {
509         errln("FAIL inserting \"test\"");
510         }
511         length = UTF16.insert(array, length, 5, 't');
512         length = UTF16.insert(array, length, 5, 's');
513         length = UTF16.insert(array, length, 5, 'e');
514         length = UTF16.insert(array, length, 5, 't');
515         String str = new String(array, 0, length);
516         if (!(str.equals("01234test56789"))) {
517         errln("FAIL inserting \"test\"");
518         }
519         UTF16.insert(strbuff, 0, 0x10000);
520         UTF16.insert(strbuff, 11, 0x10000);
521         UTF16.insert(strbuff, strbuff.length(), 0x10000);
522         if (!(strbuff.toString().equals(
523                     "\ud800\udc0001234test\ud800\udc0056789\ud800\udc00"))) {
524         errln("FAIL inserting supplementary characters");
525         }
526         length = UTF16.insert(array, length, 0, 0x10000);
527         length = UTF16.insert(array, length, 11, 0x10000);
528         length = UTF16.insert(array, length, length, 0x10000);
529         str = new String(array, 0, length);
530         if (!(str.equals(
531              "\ud800\udc0001234test\ud800\udc0056789\ud800\udc00"))) {
532         errln("FAIL inserting supplementary characters");
533         }
534 
535         try {
536         UTF16.insert(strbuff, -1, 0);
537         errln("FAIL invalid insertion offset");
538         } catch (Exception e) {
539         System.out.print("");
540         }
541         try {
542         UTF16.insert(strbuff, 64, 0);
543         errln("FAIL invalid insertion offset");
544         } catch (Exception e) {
545         System.out.print("");
546         }
547         try {
548         UTF16.insert(array, length, -1, 0);
549         errln("FAIL invalid insertion offset");
550         } catch (Exception e) {
551         System.out.print("");
552         }
553         try {
554         UTF16.insert(array, length, 64, 0);
555         errln("FAIL invalid insertion offset");
556         } catch (Exception e) {
557         System.out.print("");
558         }
559         try {
560         // exceeded array size
561         UTF16.insert(array, array.length, 64, 0);
562         errln("FAIL invalid insertion offset");
563         } catch (Exception e) {
564         System.out.print("");
565         }
566     }
567 
568     /*
569      * Testing moveCodePointOffset APIs
570      */
571 
572     //
573     //   checkMoveCodePointOffset
574     //      Run a single test case through each of the moveCodePointOffset() functions.
575     //          Parameters -
576     //              s               The string to work in.
577     //              startIdx        The starting position within the string.
578     //              amount          The number of code points to move.
579     //              expectedResult  The string index after the move, or -1 if the
580     //                              function should throw an exception.
checkMoveCodePointOffset(String s, int startIdx, int amount, int expectedResult)581     private void checkMoveCodePointOffset(String s, int startIdx, int amount, int expectedResult) {
582         // Test with the String flavor of moveCodePointOffset
583         try {
584             int result = UTF16.moveCodePointOffset(s, startIdx, amount);
585             if (result != expectedResult) {
586                 errln("FAIL: UTF16.moveCodePointOffset(String \"" + s + "\", " + startIdx + ", " + amount + ")" +
587                         " returned "  + result + ", expected result was " +
588                         (expectedResult==-1 ? "exception" : Integer.toString(expectedResult)));
589             }
590         }
591         catch (IndexOutOfBoundsException e) {
592             if (expectedResult != -1) {
593                 errln("FAIL: UTF16.moveCodePointOffset(String \"" + s + "\", " + startIdx + ", " + amount + ")" +
594                         " returned exception" + ", expected result was " + expectedResult);
595             }
596         }
597 
598         // Test with the StringBuffer flavor of moveCodePointOffset
599         StringBuffer sb = new StringBuffer(s);
600         try {
601             int result = UTF16.moveCodePointOffset(sb, startIdx, amount);
602             if (result != expectedResult) {
603                 errln("FAIL: UTF16.moveCodePointOffset(StringBuffer \"" + s + "\", " + startIdx + ", " + amount + ")" +
604                         " returned "  + result + ", expected result was " +
605                         (expectedResult==-1 ? "exception" : Integer.toString(expectedResult)));
606             }
607         }
608         catch (IndexOutOfBoundsException e) {
609             if (expectedResult != -1) {
610                 errln("FAIL: UTF16.moveCodePointOffset(StringBuffer \"" + s + "\", " + startIdx + ", " + amount + ")" +
611                         " returned exception" + ", expected result was " + expectedResult);
612             }
613         }
614 
615         // Test with the char[] flavor of moveCodePointOffset
616         char ca[] = s.toCharArray();
617         try {
618             int result = UTF16.moveCodePointOffset(ca, 0, s.length(), startIdx, amount);
619             if (result != expectedResult) {
620                 errln("FAIL: UTF16.moveCodePointOffset(char[] \"" + s + "\", 0, " + s.length()
621                         + ", " + startIdx + ", " + amount + ")" +
622                         " returned "  + result + ", expected result was " +
623                         (expectedResult==-1 ? "exception" : Integer.toString(expectedResult)));
624             }
625         }
626         catch (IndexOutOfBoundsException e) {
627             if (expectedResult != -1) {
628                 errln("FAIL: UTF16.moveCodePointOffset(char[] \"" + s + "\", 0, " + s.length()
629                         + ", " + startIdx + ", " + amount + ")" +
630                         " returned exception" + ", expected result was " + expectedResult);
631             }
632         }
633 
634         // Put the test string into the interior of a char array,
635         //   run test on the subsection of the array.
636         char ca2[] = new char[s.length()+2];
637         ca2[0] = (char)0xd800;
638         ca2[s.length()+1] = (char)0xd8ff;
639         s.getChars(0, s.length(), ca2, 1);
640         try {
641             int result = UTF16.moveCodePointOffset(ca2, 1, s.length()+1, startIdx, amount);
642             if (result != expectedResult) {
643                 errln("UTF16.moveCodePointOffset(char[] \"" + "." + s + ".\", 1, " + (s.length()+1)
644                         + ", " + startIdx + ", " + amount + ")" +
645                          " returned "  + result + ", expected result was " +
646                         (expectedResult==-1 ? "exception" : Integer.toString(expectedResult)));
647             }
648         }
649         catch (IndexOutOfBoundsException e) {
650             if (expectedResult != -1) {
651                 errln("UTF16.moveCodePointOffset(char[] \"" + "." + s + ".\", 1, " + (s.length()+1)
652                         + ", " + startIdx + ", " + amount + ")" +
653                         " returned exception" + ", expected result was " + expectedResult);
654             }
655         }
656 
657     }
658 
659 
TestMoveCodePointOffset()660     public void TestMoveCodePointOffset()
661     {
662         // checkMoveCodePointOffset(String, startIndex, amount, expected );  expected=-1 for exception.
663 
664         // No Supplementary chars
665         checkMoveCodePointOffset("abc", 1,  1, 2);
666         checkMoveCodePointOffset("abc", 1, -1, 0);
667         checkMoveCodePointOffset("abc", 1, -2, -1);
668         checkMoveCodePointOffset("abc", 1,  2, 3);
669         checkMoveCodePointOffset("abc", 1,  3, -1);
670         checkMoveCodePointOffset("abc", 1,  0, 1);
671 
672         checkMoveCodePointOffset("abc", 3, 0, 3);
673         checkMoveCodePointOffset("abc", 4, 0, -1);
674         checkMoveCodePointOffset("abc", 0, 0, 0);
675         checkMoveCodePointOffset("abc", -1, 0, -1);
676 
677         checkMoveCodePointOffset("", 0, 0, 0);
678         checkMoveCodePointOffset("", 0, -1, -1);
679         checkMoveCodePointOffset("", 0, 1, -1);
680 
681         checkMoveCodePointOffset("a", 0, 0, 0);
682         checkMoveCodePointOffset("a", 1, 0, 1);
683         checkMoveCodePointOffset("a", 0, 1, 1);
684         checkMoveCodePointOffset("a", 1, -1, 0);
685 
686 
687         // Supplementary in middle of string
688         checkMoveCodePointOffset("a\ud800\udc00b", 0, 1, 1);
689         checkMoveCodePointOffset("a\ud800\udc00b", 0, 2, 3);
690         checkMoveCodePointOffset("a\ud800\udc00b", 0, 3, 4);
691         checkMoveCodePointOffset("a\ud800\udc00b", 0, 4, -1);
692 
693         checkMoveCodePointOffset("a\ud800\udc00b", 4, -1, 3);
694         checkMoveCodePointOffset("a\ud800\udc00b", 4, -2, 1);
695         checkMoveCodePointOffset("a\ud800\udc00b", 4, -3, 0);
696         checkMoveCodePointOffset("a\ud800\udc00b", 4, -4, -1);
697 
698         // Supplementary at start of string
699         checkMoveCodePointOffset("\ud800\udc00ab", 0, 1, 2);
700         checkMoveCodePointOffset("\ud800\udc00ab", 1, 1, 2);
701         checkMoveCodePointOffset("\ud800\udc00ab", 2, 1, 3);
702         checkMoveCodePointOffset("\ud800\udc00ab", 2, -1, 0);
703         checkMoveCodePointOffset("\ud800\udc00ab", 1, -1, 0);
704         checkMoveCodePointOffset("\ud800\udc00ab", 0, -1, -1);
705 
706 
707         // Supplementary at end of string
708         checkMoveCodePointOffset("ab\ud800\udc00", 1, 1, 2);
709         checkMoveCodePointOffset("ab\ud800\udc00", 2, 1, 4);
710         checkMoveCodePointOffset("ab\ud800\udc00", 3, 1, 4);
711         checkMoveCodePointOffset("ab\ud800\udc00", 4, 1, -1);
712 
713         checkMoveCodePointOffset("ab\ud800\udc00", 5, -2, -1);
714         checkMoveCodePointOffset("ab\ud800\udc00", 4, -1, 2);
715         checkMoveCodePointOffset("ab\ud800\udc00", 3, -1, 2);
716         checkMoveCodePointOffset("ab\ud800\udc00", 2, -1, 1);
717         checkMoveCodePointOffset("ab\ud800\udc00", 1, -1, 0);
718 
719         // Unpaired surrogate in middle
720         checkMoveCodePointOffset("a\ud800b", 0, 1, 1);
721         checkMoveCodePointOffset("a\ud800b", 1, 1, 2);
722         checkMoveCodePointOffset("a\ud800b", 2, 1, 3);
723 
724         checkMoveCodePointOffset("a\udc00b", 0, 1, 1);
725         checkMoveCodePointOffset("a\udc00b", 1, 1, 2);
726         checkMoveCodePointOffset("a\udc00b", 2, 1, 3);
727 
728         checkMoveCodePointOffset("a\udc00\ud800b", 0, 1, 1);
729         checkMoveCodePointOffset("a\udc00\ud800b", 1, 1, 2);
730         checkMoveCodePointOffset("a\udc00\ud800b", 2, 1, 3);
731         checkMoveCodePointOffset("a\udc00\ud800b", 3, 1, 4);
732 
733         checkMoveCodePointOffset("a\ud800b", 1, -1, 0);
734         checkMoveCodePointOffset("a\ud800b", 2, -1, 1);
735         checkMoveCodePointOffset("a\ud800b", 3, -1, 2);
736 
737         checkMoveCodePointOffset("a\udc00b", 1, -1, 0);
738         checkMoveCodePointOffset("a\udc00b", 2, -1, 1);
739         checkMoveCodePointOffset("a\udc00b", 3, -1, 2);
740 
741         checkMoveCodePointOffset("a\udc00\ud800b", 1, -1, 0);
742         checkMoveCodePointOffset("a\udc00\ud800b", 2, -1, 1);
743         checkMoveCodePointOffset("a\udc00\ud800b", 3, -1, 2);
744         checkMoveCodePointOffset("a\udc00\ud800b", 4, -1, 3);
745 
746         // Unpaired surrogate at start
747         checkMoveCodePointOffset("\udc00ab", 0, 1, 1);
748         checkMoveCodePointOffset("\ud800ab", 0, 2, 2);
749         checkMoveCodePointOffset("\ud800\ud800ab", 0, 3, 3);
750         checkMoveCodePointOffset("\udc00\udc00ab", 0, 4, 4);
751 
752         checkMoveCodePointOffset("\udc00ab", 2, -1, 1);
753         checkMoveCodePointOffset("\ud800ab", 1, -1, 0);
754         checkMoveCodePointOffset("\ud800ab", 1, -2, -1);
755         checkMoveCodePointOffset("\ud800\ud800ab", 2, -1, 1);
756         checkMoveCodePointOffset("\udc00\udc00ab", 2, -2, 0);
757         checkMoveCodePointOffset("\udc00\udc00ab", 2, -3, -1);
758 
759         // Unpaired surrogate at end
760         checkMoveCodePointOffset("ab\udc00\udc00ab", 3, 1, 4);
761         checkMoveCodePointOffset("ab\udc00\udc00ab", 2, 1, 3);
762         checkMoveCodePointOffset("ab\udc00\udc00ab", 1, 1, 2);
763 
764         checkMoveCodePointOffset("ab\udc00\udc00ab", 4, -1, 3);
765         checkMoveCodePointOffset("ab\udc00\udc00ab", 3, -1, 2);
766         checkMoveCodePointOffset("ab\udc00\udc00ab", 2, -1, 1);
767 
768 
769                                //01234567890     1     2     3     45678901234
770         String str = new String("0123456789\ud800\udc00\ud801\udc010123456789");
771         int move1[] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
772                        12, 12, 14, 14, 15, 16, 17, 18, 19, 20,
773                        21, 22, 23, 24};
774         int move2[] = { 2,  3,  4,  5,  6,  7,  8,  9, 10, 12,
775                        14, 14, 15, 15, 16, 17, 18, 19, 20, 21,
776                        22, 23, 24, -1};
777         int move3[] = { 3,  4,  5,  6,  7,  8,  9, 10, 12, 14,
778                        15, 15, 16, 16, 17, 18, 19, 20, 21, 22,
779                        23, 24, -1, -1};
780         int size = str.length();
781         for (int i = 0; i < size; i ++) {
782             checkMoveCodePointOffset(str, i, 1, move1[i]);
783             checkMoveCodePointOffset(str, i, 2, move2[i]);
784             checkMoveCodePointOffset(str, i, 3, move3[i]);
785         }
786 
787         char strarray[] = str.toCharArray();
788         if (UTF16.moveCodePointOffset(strarray, 9, 13, 0, 2) != 3) {
789             errln("FAIL: Moving offset 0 by 2 codepoint in subarray [9, 13] " +
790             "expected result 3");
791         }
792         if (UTF16.moveCodePointOffset(strarray, 9, 13, 1, 2) != 4) {
793             errln("FAIL: Moving offset 1 by 2 codepoint in subarray [9, 13] " +
794             "expected result 4");
795         }
796         if (UTF16.moveCodePointOffset(strarray, 11, 14, 0, 2) != 3) {
797             errln("FAIL: Moving offset 0 by 2 codepoint in subarray [11, 14] "
798                     + "expected result 3");
799         }
800     }
801 
802     /**
803      * Testing UTF16 class methods setCharAt
804      */
TestSetCharAt()805     public void TestSetCharAt()
806     {
807         StringBuffer strbuff = new StringBuffer("012345");
808         char array[] = new char[128];
809         int srcEnd = strbuff.length();
810         if (0 != srcEnd) {
811             strbuff.getChars(0, srcEnd, array, 0);
812         }
813         int length = 6;
814         for (int i = 0; i < length; i ++) {
815         UTF16.setCharAt(strbuff, i, '0');
816         UTF16.setCharAt(array, length, i, '0');
817         }
818         String str = new String(array, 0, length);
819         if (!(strbuff.toString().equals("000000")) ||
820         !(str.equals("000000"))) {
821         errln("FAIL: setChar to '0' failed");
822         }
823         UTF16.setCharAt(strbuff, 0, 0x10000);
824         UTF16.setCharAt(strbuff, 4, 0x10000);
825         UTF16.setCharAt(strbuff, 7, 0x10000);
826         if (!(strbuff.toString().equals(
827                     "\ud800\udc0000\ud800\udc000\ud800\udc00"))) {
828         errln("FAIL: setChar to 0x10000 failed");
829         }
830         length = UTF16.setCharAt(array, length, 0, 0x10000);
831         length = UTF16.setCharAt(array, length, 4, 0x10000);
832         length = UTF16.setCharAt(array, length, 7, 0x10000);
833         str = new String(array, 0, length);
834         if (!(str.equals("\ud800\udc0000\ud800\udc000\ud800\udc00"))) {
835         errln("FAIL: setChar to 0x10000 failed");
836         }
837         UTF16.setCharAt(strbuff, 0, '0');
838         UTF16.setCharAt(strbuff, 1, '1');
839         UTF16.setCharAt(strbuff, 2, '2');
840         UTF16.setCharAt(strbuff, 4, '3');
841         UTF16.setCharAt(strbuff, 4, '4');
842         UTF16.setCharAt(strbuff, 5, '5');
843         if (!strbuff.toString().equals("012345")) {
844         errln("Fail converting supplementaries in StringBuffer to BMP " +
845           "characters");
846         }
847         length = UTF16.setCharAt(array, length, 0, '0');
848         length = UTF16.setCharAt(array, length, 1, '1');
849         length = UTF16.setCharAt(array, length, 2, '2');
850         length = UTF16.setCharAt(array, length, 4, '3');
851         length = UTF16.setCharAt(array, length, 4, '4');
852         length = UTF16.setCharAt(array, length, 5, '5');
853         str = new String(array, 0, length);
854         if (!str.equals("012345")) {
855         errln("Fail converting supplementaries in array to BMP " +
856           "characters");
857         }
858         try {
859         UTF16.setCharAt(strbuff, -1, 0);
860         errln("FAIL: setting character at invalid offset");
861         } catch (Exception e) {
862         System.out.print("");
863         }
864         try {
865         UTF16.setCharAt(array, length, -1, 0);
866         errln("FAIL: setting character at invalid offset");
867         } catch (Exception e) {
868         System.out.print("");
869         }
870         try {
871         UTF16.setCharAt(strbuff, length, 0);
872         errln("FAIL: setting character at invalid offset");
873         } catch (Exception e) {
874         System.out.print("");
875         }
876         try {
877         UTF16.setCharAt(array, length, length, 0);
878         errln("FAIL: setting character at invalid offset");
879         } catch (Exception e) {
880         System.out.print("");
881         }
882     }
883 
884     /**
885      * Testing UTF16 valueof APIs
886      */
TestValueOf()887     public void TestValueOf()
888     {
889         if(UCharacter.getCodePoint('\ud800','\udc00')!=0x10000){
890             errln("FAIL: getCodePoint('\ud800','\udc00')");
891         }
892         if (!UTF16.valueOf(0x61).equals("a") ||
893         !UTF16.valueOf(0x10000).equals("\ud800\udc00")) {
894         errln("FAIL: valueof(char32)");
895         }
896         String str = new String("01234\ud800\udc0056789");
897         StringBuffer strbuff = new StringBuffer(str);
898         char array[] = str.toCharArray();
899         int length = str.length();
900 
901         String expected[] = {"0", "1", "2", "3", "4", "\ud800\udc00",
902                  "\ud800\udc00", "5", "6", "7", "8", "9"};
903         for (int i = 0; i < length; i ++) {
904         if (!UTF16.valueOf(str, i).equals(expected[i]) ||
905                 !UTF16.valueOf(strbuff, i).equals(expected[i]) ||
906                 !UTF16.valueOf(array, 0, length, i).equals(expected[i])) {
907                 errln("FAIL: valueOf() expected " + expected[i]);
908         }
909         }
910         try {
911         UTF16.valueOf(str, -1);
912         errln("FAIL: out of bounds error expected");
913         } catch (Exception e) {
914         System.out.print("");
915         }
916         try {
917         UTF16.valueOf(strbuff, -1);
918         errln("FAIL: out of bounds error expected");
919         } catch (Exception e) {
920         System.out.print("");
921         }
922         try {
923         UTF16.valueOf(array, 0, length, -1);
924         errln("FAIL: out of bounds error expected");
925         } catch (Exception e) {
926         System.out.print("");
927         }
928         try {
929         UTF16.valueOf(str, length);
930         errln("FAIL: out of bounds error expected");
931         } catch (Exception e) {
932         System.out.print("");
933         }
934         try {
935         UTF16.valueOf(strbuff, length);
936         errln("FAIL: out of bounds error expected");
937         } catch (Exception e) {
938         System.out.print("");
939         }
940         try {
941         UTF16.valueOf(array, 0, length, length);
942         errln("FAIL: out of bounds error expected");
943         } catch (Exception e) {
944         System.out.print("");
945         }
946         if (!UTF16.valueOf(array, 6, length, 0).equals("\udc00") ||
947         !UTF16.valueOf(array, 0, 6, 5).equals("\ud800")) {
948         errln("FAIL: error getting partial supplementary character");
949         }
950         try {
951         UTF16.valueOf(array, 3, 5, -1);
952         errln("FAIL: out of bounds error expected");
953         } catch (Exception e) {
954         System.out.print("");
955         }
956         try {
957         UTF16.valueOf(array, 3, 5, 3);
958         errln("FAIL: out of bounds error expected");
959         } catch (Exception e) {
960         System.out.print("");
961         }
962     }
963 
TestIndexOf()964     public void TestIndexOf()
965     {
966     //012345678901234567890123456789012345
967         String test1     = "test test ttest tetest testesteststt";
968         String test2     = "test";
969         int    testChar1 = 0x74;
970         int    testChar2 = 0x20402;
971         // int    testChar3 = 0xdc02;
972         // int    testChar4 = 0xd841;
973         String test3     = "\ud841\udc02\u0071\udc02\ud841\u0071\ud841\udc02\u0071\u0072\ud841\udc02\u0071\ud841\udc02\u0071\udc02\ud841\u0073";
974         String test4     = UCharacter.toString(testChar2);
975 
976         if (UTF16.indexOf(test1, test2) != 0 ||
977             UTF16.indexOf(test1, test2, 0) != 0) {
978             errln("indexOf failed: expected to find '" + test2 +
979                   "' at position 0 in text '" + test1 + "'");
980         }
981         if (UTF16.indexOf(test1, testChar1) != 0 ||
982             UTF16.indexOf(test1, testChar1, 0) != 0) {
983             errln("indexOf failed: expected to find 0x" +
984                   Integer.toHexString(testChar1) +
985                   " at position 0 in text '" + test1 + "'");
986         }
987         if (UTF16.indexOf(test3, testChar2) != 0 ||
988             UTF16.indexOf(test3, testChar2, 0) != 0) {
989             errln("indexOf failed: expected to find 0x" +
990                   Integer.toHexString(testChar2) +
991                   " at position 0 in text '" + Utility.hex(test3) + "'");
992         }
993         String test5 = "\ud841\ud841\udc02";
994         if (UTF16.indexOf(test5, testChar2) != 1 ||
995             UTF16.indexOf(test5, testChar2, 0) != 1) {
996             errln("indexOf failed: expected to find 0x" +
997                   Integer.toHexString(testChar2) +
998                   " at position 0 in text '" + Utility.hex(test3) + "'");
999         }
1000         if (UTF16.lastIndexOf(test1, test2) != 29 ||
1001             UTF16.lastIndexOf(test1, test2, test1.length()) != 29) {
1002             errln("lastIndexOf failed: expected to find '" + test2 +
1003                   "' at position 29 in text '" + test1 + "'");
1004         }
1005         if (UTF16.lastIndexOf(test1, testChar1) != 35 ||
1006             UTF16.lastIndexOf(test1, testChar1, test1.length()) != 35) {
1007             errln("lastIndexOf failed: expected to find 0x" +
1008                   Integer.toHexString(testChar1) +
1009                   " at position 35 in text '" + test1 + "'");
1010         }
1011         if (UTF16.lastIndexOf(test3, testChar2) != 13 ||
1012             UTF16.lastIndexOf(test3, testChar2, test3.length()) != 13) {
1013             errln("indexOf failed: expected to find 0x" +
1014                   Integer.toHexString(testChar2) +
1015                   " at position 13 in text '" + Utility.hex(test3) + "'");
1016         }
1017         int occurrences = 0;
1018         for (int startPos = 0; startPos != -1 && startPos < test1.length();)
1019         {
1020         startPos = UTF16.indexOf(test1, test2, startPos);
1021         if (startPos >= 0) {
1022             ++ occurrences;
1023             startPos += 4;
1024         }
1025         }
1026         if (occurrences != 6) {
1027             errln("indexOf failed: expected to find 6 occurrences, found "
1028                   + occurrences);
1029         }
1030 
1031         occurrences = 0;
1032         for (int startPos = 10; startPos != -1 && startPos < test1.length();)
1033         {
1034         startPos = UTF16.indexOf(test1, test2, startPos);
1035         if (startPos >= 0) {
1036             ++ occurrences;
1037             startPos += 4;
1038         }
1039         }
1040         if (occurrences != 4) {
1041             errln("indexOf with starting offset failed: expected to find 4 occurrences, found "
1042                   + occurrences);
1043         }
1044 
1045         occurrences = 0;
1046         for (int startPos = 0;
1047          startPos != -1 && startPos < test3.length();) {
1048             startPos = UTF16.indexOf(test3, test4, startPos);
1049             if (startPos != -1) {
1050                 ++ occurrences;
1051                 startPos += 2;
1052             }
1053         }
1054         if (occurrences != 4) {
1055             errln("indexOf failed: expected to find 4 occurrences, found "
1056           + occurrences);
1057         }
1058 
1059         occurrences = 0;
1060         for (int startPos = 10;
1061              startPos != -1 && startPos < test3.length();) {
1062             startPos = UTF16.indexOf(test3, test4, startPos);
1063             if (startPos != -1) {
1064                 ++ occurrences;
1065                 startPos += 2;
1066             }
1067         }
1068         if (occurrences != 2) {
1069             errln("indexOf failed: expected to find 2 occurrences, found "
1070                   + occurrences);
1071         }
1072 
1073         occurrences = 0;
1074         for (int startPos = 0;
1075          startPos != -1 && startPos < test1.length();) {
1076             startPos = UTF16.indexOf(test1, testChar1, startPos);
1077             if (startPos != -1) {
1078                 ++ occurrences;
1079                 startPos += 1;
1080             }
1081         }
1082         if (occurrences != 16) {
1083             errln("indexOf with character failed: expected to find 16 occurrences, found "
1084                   + occurrences);
1085         }
1086 
1087         occurrences = 0;
1088         for (int startPos = 10;
1089          startPos != -1 && startPos < test1.length();) {
1090             startPos = UTF16.indexOf(test1, testChar1, startPos);
1091             if (startPos != -1) {
1092                 ++ occurrences;
1093                 startPos += 1;
1094             }
1095         }
1096         if (occurrences != 12) {
1097             errln("indexOf with character & start offset failed: expected to find 12 occurrences, found "
1098           + occurrences);
1099         }
1100 
1101         occurrences = 0;
1102         for (int startPos = 0;
1103          startPos != -1 && startPos < test3.length();) {
1104             startPos = UTF16.indexOf(test3, testChar2, startPos);
1105             if (startPos != -1) {
1106                 ++ occurrences;
1107                 startPos += 1;
1108             }
1109         }
1110         if (occurrences != 4) {
1111             errln("indexOf failed: expected to find 4 occurrences, found "
1112                   + occurrences);
1113         }
1114 
1115         occurrences = 0;
1116         for (int startPos = 5; startPos != -1 && startPos < test3.length();) {
1117             startPos = UTF16.indexOf(test3, testChar2, startPos);
1118             if (startPos != -1) {
1119                 ++ occurrences;
1120                 startPos += 1;
1121             }
1122         }
1123         if (occurrences != 3) {
1124             errln("indexOf with character & start & end offsets failed: expected to find 2 occurrences, found "
1125           + occurrences);
1126         }
1127         occurrences = 0;
1128         for (int startPos = 32; startPos != -1;) {
1129             startPos = UTF16.lastIndexOf(test1, test2, startPos);
1130             if (startPos != -1) {
1131                 ++ occurrences;
1132                 startPos -= 5;
1133             }
1134         }
1135         if (occurrences != 6) {
1136             errln("lastIndexOf with starting and ending offsets failed: expected to find 4 occurrences, found "
1137                   + occurrences);
1138         }
1139         occurrences = 0;
1140         for (int startPos = 32; startPos != -1;) {
1141             startPos = UTF16.lastIndexOf(test1, testChar1, startPos);
1142             if (startPos != -1) {
1143                 ++ occurrences;
1144                 startPos -= 5;
1145             }
1146         }
1147         if (occurrences != 7) {
1148             errln("lastIndexOf with character & start & end offsets failed: expected to find 11 occurrences, found "
1149           + occurrences);
1150         }
1151 
1152         //testing UChar32
1153         occurrences = 0;
1154         for (int startPos = test3.length(); startPos != -1;) {
1155             startPos = UTF16.lastIndexOf(test3, testChar2, startPos - 5);
1156             if (startPos != -1) {
1157                 ++ occurrences;
1158             }
1159         }
1160         if (occurrences != 3) {
1161             errln("lastIndexOf with character & start & end offsets failed: expected to find 3 occurrences, found "
1162           + occurrences);
1163         }
1164 
1165         // testing supplementary
1166         for (int i = 0; i < INDEXOF_SUPPLEMENTARY_CHAR_.length; i ++) {
1167         int ch = INDEXOF_SUPPLEMENTARY_CHAR_[i];
1168         for (int j = 0; j < INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i].length;
1169          j ++) {
1170         int index = 0;
1171         int expected = INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i][j];
1172         if  (j > 0) {
1173             index = INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i][j - 1] + 1;
1174         }
1175         if (UTF16.indexOf(INDEXOF_SUPPLEMENTARY_STRING_, ch, index) !=
1176             expected ||
1177             UTF16.indexOf(INDEXOF_SUPPLEMENTARY_STRING_,
1178                   UCharacter.toString(ch), index) !=
1179             expected) {
1180             errln("Failed finding index for supplementary 0x" +
1181               Integer.toHexString(ch));
1182         }
1183         index = INDEXOF_SUPPLEMENTARY_STRING_.length();
1184         if (j < INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i].length - 1) {
1185             index = INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i][j + 1] - 1;
1186         }
1187         if (UTF16.lastIndexOf(INDEXOF_SUPPLEMENTARY_STRING_, ch,
1188                       index) != expected ||
1189             UTF16.lastIndexOf(INDEXOF_SUPPLEMENTARY_STRING_,
1190                       UCharacter.toString(ch), index)
1191             != expected)
1192             {
1193             errln("Failed finding last index for supplementary 0x" +
1194                   Integer.toHexString(ch));
1195             }
1196         }
1197         }
1198 
1199         for (int i = 0; i < INDEXOF_SUPPLEMENTARY_STR_INDEX_.length; i ++) {
1200         int index = 0;
1201         int expected = INDEXOF_SUPPLEMENTARY_STR_INDEX_[i];
1202         if  (i > 0) {
1203         index = INDEXOF_SUPPLEMENTARY_STR_INDEX_[i - 1] + 1;
1204         }
1205         if (UTF16.indexOf(INDEXOF_SUPPLEMENTARY_STRING_,
1206                   INDEXOF_SUPPLEMENTARY_STR_, index) != expected) {
1207         errln("Failed finding index for supplementary string " +
1208               hex(INDEXOF_SUPPLEMENTARY_STRING_));
1209         }
1210         index = INDEXOF_SUPPLEMENTARY_STRING_.length();
1211         if (i < INDEXOF_SUPPLEMENTARY_STR_INDEX_.length - 1) {
1212         index = INDEXOF_SUPPLEMENTARY_STR_INDEX_[i + 1] - 1;
1213         }
1214         if (UTF16.lastIndexOf(INDEXOF_SUPPLEMENTARY_STRING_,
1215                               INDEXOF_SUPPLEMENTARY_STR_, index) != expected) {
1216         errln("Failed finding last index for supplementary string " +
1217               hex(INDEXOF_SUPPLEMENTARY_STRING_));
1218         }
1219         }
1220     }
1221 
TestReplace()1222     public void TestReplace()
1223     {
1224         String test1 = "One potato, two potato, three potato, four\n";
1225         String test2 = "potato";
1226         String test3 = "MISSISSIPPI";
1227 
1228         String result = UTF16.replace(test1, test2, test3);
1229         String expectedValue =
1230             "One MISSISSIPPI, two MISSISSIPPI, three MISSISSIPPI, four\n";
1231         if (!result.equals(expectedValue)) {
1232             errln("findAndReplace failed: expected \"" + expectedValue +
1233                   "\", got \"" + test1 + "\".");
1234         }
1235         result = UTF16.replace(test1, test3, test2);
1236         expectedValue = test1;
1237         if (!result.equals(expectedValue)) {
1238             errln("findAndReplace failed: expected \"" + expectedValue +
1239                   "\", got \"" + test1 + "\".");
1240         }
1241 
1242         result = UTF16.replace(test1, ',', 'e');
1243         expectedValue = "One potatoe two potatoe three potatoe four\n";
1244         if (!result.equals(expectedValue)) {
1245             errln("findAndReplace failed: expected \"" + expectedValue +
1246                   "\", got \"" + test1 + "\".");
1247         }
1248 
1249         result = UTF16.replace(test1, ',', 0x10000);
1250         expectedValue = "One potato\ud800\udc00 two potato\ud800\udc00 three potato\ud800\udc00 four\n";
1251         if (!result.equals(expectedValue)) {
1252             errln("findAndReplace failed: expected \"" + expectedValue +
1253                   "\", got \"" + test1 + "\".");
1254         }
1255 
1256         result = UTF16.replace(test1, "potato", "\ud800\udc00\ud801\udc01");
1257         expectedValue = "One \ud800\udc00\ud801\udc01, two \ud800\udc00\ud801\udc01, three \ud800\udc00\ud801\udc01, four\n";
1258         if (!result.equals(expectedValue)) {
1259             errln("findAndReplace failed: expected \"" + expectedValue +
1260                   "\", got \"" + test1 + "\".");
1261         }
1262 
1263         String test4 = "\ud800\ud800\udc00\ud800\udc00\udc00\ud800\ud800\udc00\ud800\udc00\udc00";
1264         result = UTF16.replace(test4, 0xd800, 'A');
1265         expectedValue = "A\ud800\udc00\ud800\udc00\udc00A\ud800\udc00\ud800\udc00\udc00";
1266         if (!result.equals(expectedValue)) {
1267             errln("findAndReplace failed: expected \"" + expectedValue +
1268                   "\", got \"" + test1 + "\".");
1269         }
1270 
1271         result = UTF16.replace(test4, 0xdC00, 'A');
1272         expectedValue = "\ud800\ud800\udc00\ud800\udc00A\ud800\ud800\udc00\ud800\udc00A";
1273         if (!result.equals(expectedValue)) {
1274             errln("findAndReplace failed: expected \"" + expectedValue +
1275                   "\", got \"" + test1 + "\".");
1276         }
1277 
1278         result = UTF16.replace(test4, 0x10000, 'A');
1279         expectedValue = "\ud800AA\udc00\ud800AA\udc00";
1280         if (!result.equals(expectedValue)) {
1281             errln("findAndReplace failed: expected \"" + expectedValue +
1282                   "\", got \"" + test1 + "\".");
1283         }
1284     }
1285 
TestReverse()1286     public void TestReverse()
1287     {
1288         StringBuffer test = new StringBuffer(
1289                          "backwards words say to used I");
1290 
1291         StringBuffer result = UTF16.reverse(test);
1292         if (!result.toString().equals("I desu ot yas sdrow sdrawkcab")) {
1293             errln("reverse() failed:  Expected \"I desu ot yas sdrow sdrawkcab\",\n got \""
1294           + result + "\"");
1295         }
1296         StringBuffer testbuffer = new StringBuffer();
1297         UTF16.append(testbuffer, 0x2f999);
1298         UTF16.append(testbuffer, 0x1d15f);
1299         UTF16.append(testbuffer, 0x00c4);
1300         UTF16.append(testbuffer, 0x1ed0);
1301         result = UTF16.reverse(testbuffer);
1302         if (result.charAt(0) != 0x1ed0 ||
1303             result.charAt(1) != 0xc4 ||
1304             UTF16.charAt(result, 2) != 0x1d15f ||
1305             UTF16.charAt(result, 4)!=0x2f999) {
1306             errln("reverse() failed with supplementary characters");
1307         }
1308     }
1309 
1310     /**
1311      * Testing the setter and getter apis for StringComparator
1312      */
TestStringComparator()1313     public void TestStringComparator()
1314     {
1315         UTF16.StringComparator compare = new UTF16.StringComparator();
1316         if (compare.getCodePointCompare() != false) {
1317             errln("Default string comparator should be code unit compare");
1318         }
1319         if (compare.getIgnoreCase() != false) {
1320             errln("Default string comparator should be case sensitive compare");
1321         }
1322         if (compare.getIgnoreCaseOption()
1323             != UTF16.StringComparator.FOLD_CASE_DEFAULT) {
1324             errln("Default string comparator should have fold case default compare");
1325         }
1326         compare.setCodePointCompare(true);
1327         if (compare.getCodePointCompare() != true) {
1328             errln("Error setting code point compare");
1329         }
1330         compare.setCodePointCompare(false);
1331         if (compare.getCodePointCompare() != false) {
1332             errln("Error setting code point compare");
1333         }
1334         compare.setIgnoreCase(true, UTF16.StringComparator.FOLD_CASE_DEFAULT);
1335         if (compare.getIgnoreCase() != true
1336             || compare.getIgnoreCaseOption()
1337         != UTF16.StringComparator.FOLD_CASE_DEFAULT) {
1338             errln("Error setting ignore case and options");
1339         }
1340         compare.setIgnoreCase(false, UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I);
1341         if (compare.getIgnoreCase() != false
1342             || compare.getIgnoreCaseOption()
1343         != UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I) {
1344             errln("Error setting ignore case and options");
1345         }
1346         compare.setIgnoreCase(true, UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I);
1347         if (compare.getIgnoreCase() != true
1348             || compare.getIgnoreCaseOption()
1349         != UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I) {
1350             errln("Error setting ignore case and options");
1351         }
1352         compare.setIgnoreCase(false, UTF16.StringComparator.FOLD_CASE_DEFAULT);
1353         if (compare.getIgnoreCase() != false
1354             || compare.getIgnoreCaseOption()
1355         != UTF16.StringComparator.FOLD_CASE_DEFAULT) {
1356             errln("Error setting ignore case and options");
1357         }
1358     }
1359 
TestCodePointCompare()1360     public void TestCodePointCompare()
1361     {
1362         // these strings are in ascending order
1363         String str[] = {"\u0061", "\u20ac\ud801", "\u20ac\ud800\udc00",
1364                         "\ud800", "\ud800\uff61", "\udfff",
1365                         "\uff61\udfff", "\uff61\ud800\udc02", "\ud800\udc02",
1366                         "\ud84d\udc56"};
1367         UTF16.StringComparator cpcompare
1368             = new UTF16.StringComparator(true, false,
1369                      UTF16.StringComparator.FOLD_CASE_DEFAULT);
1370         UTF16.StringComparator cucompare
1371             = new UTF16.StringComparator();
1372         for (int i = 0; i < str.length - 1; ++ i) {
1373             if (cpcompare.compare(str[i], str[i + 1]) >= 0) {
1374                 errln("error: compare() in code point order fails for string "
1375                       + Utility.hex(str[i]) + " and "
1376                       + Utility.hex(str[i + 1]));
1377             }
1378             // test code unit compare
1379             if (cucompare.compare(str[i], str[i + 1])
1380                 != str[i].compareTo(str[i + 1])) {
1381                 errln("error: compare() in code unit order fails for string "
1382                       + Utility.hex(str[i]) + " and "
1383                       + Utility.hex(str[i + 1]));
1384             }
1385         }
1386     }
1387 
TestCaseCompare()1388     public void TestCaseCompare()
1389     {
1390         String mixed = "\u0061\u0042\u0131\u03a3\u00df\ufb03\ud93f\udfff";
1391         String otherDefault = "\u0041\u0062\u0131\u03c3\u0073\u0053\u0046\u0066\u0049\ud93f\udfff";
1392         String otherExcludeSpecialI = "\u0041\u0062\u0131\u03c3\u0053\u0073\u0066\u0046\u0069\ud93f\udfff";
1393         String different = "\u0041\u0062\u0131\u03c3\u0073\u0053\u0046\u0066\u0049\ud93f\udffd";
1394 
1395         UTF16.StringComparator compare = new UTF16.StringComparator();
1396         compare.setIgnoreCase(true, UTF16.StringComparator.FOLD_CASE_DEFAULT);
1397         // test u_strcasecmp()
1398         int result = compare.compare(mixed, otherDefault);
1399         if (result != 0) {
1400             errln("error: default compare(mixed, other) = " + result
1401                   + " instead of 0");
1402         }
1403 
1404         // test u_strcasecmp() - exclude special i
1405         compare.setIgnoreCase(true,
1406                   UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I);
1407         result = compare.compare(mixed, otherExcludeSpecialI);
1408         if (result != 0) {
1409             errln("error: exclude_i compare(mixed, other) = " + result
1410                   + " instead of 0");
1411         }
1412 
1413         // test u_strcasecmp()
1414         compare.setIgnoreCase(true,
1415                               UTF16.StringComparator.FOLD_CASE_DEFAULT);
1416         result = compare.compare(mixed, different);
1417         if (result <= 0) {
1418             errln("error: default compare(mixed, different) = " + result
1419                   + " instead of positive");
1420         }
1421 
1422         // test substrings - stop before the sharp s (U+00df)
1423         compare.setIgnoreCase(true,
1424                               UTF16.StringComparator.FOLD_CASE_DEFAULT);
1425         result = compare.compare(mixed.substring(0, 4),
1426                                  different.substring(0, 4));
1427         if (result != 0) {
1428             errln("error: default compare(mixed substring, different substring) = "
1429           + result + " instead of 0");
1430         }
1431         // test substrings - stop in the middle of the sharp s (U+00df)
1432         compare.setIgnoreCase(true,
1433                               UTF16.StringComparator.FOLD_CASE_DEFAULT);
1434         result = compare.compare(mixed.substring(0, 5),
1435                                  different.substring(0, 5));
1436         if (result <= 0) {
1437             errln("error: default compare(mixed substring, different substring) = "
1438           + result + " instead of positive");
1439         }
1440     }
1441 
TestHasMoreCodePointsThan()1442     public void TestHasMoreCodePointsThan()
1443     {
1444         String str = "\u0061\u0062\ud800\udc00\ud801\udc01\u0063\ud802\u0064"
1445         + "\udc03\u0065\u0066\ud804\udc04\ud805\udc05\u0067";
1446         int length = str.length();
1447         while (length >= 0) {
1448             for (int i = 0; i <= length; ++ i) {
1449                 String s = str.substring(0, i);
1450                 for (int number = -1; number <= ((length - i) + 2); ++ number) {
1451                     boolean flag = UTF16.hasMoreCodePointsThan(s, number);
1452                     if (flag != (UTF16.countCodePoint(s) > number)) {
1453                         errln("hasMoreCodePointsThan(" + Utility.hex(s)
1454                               + ", " + number + ") = " + flag + " is wrong");
1455                     }
1456                 }
1457             }
1458             -- length;
1459         }
1460 
1461         // testing for null bad input
1462         for(length = -1; length <= 1; ++ length) {
1463             for (int i = 0; i <= length; ++ i) {
1464                 for (int number = -2; number <= 2; ++ number) {
1465                     boolean flag = UTF16.hasMoreCodePointsThan((String)null,
1466                                                                number);
1467                     if (flag != (UTF16.countCodePoint((String)null) > number)) {
1468                         errln("hasMoreCodePointsThan(null, " + number + ") = "
1469                   + flag + " is wrong");
1470                     }
1471                 }
1472             }
1473         }
1474 
1475         length = str.length();
1476         while (length >= 0) {
1477             for (int i = 0; i <= length; ++ i) {
1478                 StringBuffer s = new StringBuffer(str.substring(0, i));
1479                 for (int number = -1; number <= ((length - i) + 2); ++ number) {
1480                     boolean flag = UTF16.hasMoreCodePointsThan(s, number);
1481                     if (flag != (UTF16.countCodePoint(s) > number)) {
1482                         errln("hasMoreCodePointsThan(" + Utility.hex(s)
1483                               + ", " + number + ") = " + flag + " is wrong");
1484                     }
1485                 }
1486             }
1487             -- length;
1488         }
1489 
1490         // testing for null bad input
1491         for (length = -1; length <= 1; ++ length) {
1492             for (int i = 0; i <= length; ++ i) {
1493                 for (int number = -2; number <= 2; ++ number) {
1494                     boolean flag = UTF16.hasMoreCodePointsThan(
1495                                    (StringBuffer)null, number);
1496                     if (flag
1497                         != (UTF16.countCodePoint((StringBuffer)null) > number))
1498             {
1499                 errln("hasMoreCodePointsThan(null, " + number + ") = "
1500                   + flag + " is wrong");
1501             }
1502                 }
1503             }
1504         }
1505 
1506         char strarray[] = str.toCharArray();
1507         while (length >= 0) {
1508             for (int limit = 0; limit <= length; ++ limit) {
1509                 for (int start = 0; start <= limit; ++ start) {
1510                     for (int number = -1; number <= ((limit - start) + 2);
1511                          ++ number) {
1512                         boolean flag = UTF16.hasMoreCodePointsThan(strarray,
1513                                    start, limit, number);
1514                         if (flag != (UTF16.countCodePoint(strarray, start,
1515                                                           limit) > number)) {
1516                             errln("hasMoreCodePointsThan("
1517                                   + Utility.hex(str.substring(start, limit))
1518                                   + ", " + start + ", " + limit + ", " + number
1519                                   + ") = " + flag + " is wrong");
1520                         }
1521                     }
1522                 }
1523             }
1524             -- length;
1525         }
1526 
1527         // testing for null bad input
1528         for (length = -1; length <= 1; ++ length) {
1529             for (int i = 0; i <= length; ++ i) {
1530                 for (int number = -2; number <= 2; ++ number) {
1531                     boolean flag = UTF16.hasMoreCodePointsThan(
1532                                    (StringBuffer)null, number);
1533                     if (flag
1534                         != (UTF16.countCodePoint((StringBuffer)null) > number))
1535             {
1536                 errln("hasMoreCodePointsThan(null, " + number + ") = "
1537                   + flag + " is wrong");
1538             }
1539                 }
1540             }
1541         }
1542 
1543         // bad input
1544         try {
1545             UTF16.hasMoreCodePointsThan(strarray, -2, -1, 5);
1546             errln("hasMoreCodePointsThan(chararray) with negative indexes has to throw an exception");
1547         } catch (Exception e) {
1548             logln("PASS: UTF16.hasMoreCodePointsThan failed as expected");
1549         }
1550         try {
1551             UTF16.hasMoreCodePointsThan(strarray, 5, 2, 5);
1552             errln("hasMoreCodePointsThan(chararray) with limit less than start index has to throw an exception");
1553         } catch (Exception e) {
1554             logln("PASS: UTF16.hasMoreCodePointsThan failed as expected");
1555         }
1556         try {
1557             if (UTF16.hasMoreCodePointsThan(strarray, -2, 2, 5)) {
1558                 errln("hasMoreCodePointsThan(chararray) with negative start indexes can't return true");
1559             }
1560         } catch (Exception e) {
1561         }
1562     }
1563 
TestUtilities()1564     public void TestUtilities() {
1565         String[] tests = {
1566                 "a",
1567                 "\uFFFF",
1568                 "��",
1569                 "\uD800",
1570                 "\uDC00",
1571                 "\uDBFF\uDfff",
1572                 "",
1573                 "\u0000",
1574                 "\uDC00\uD800",
1575                 "ab",
1576                 "��a",
1577                 null,
1578         };
1579         StringComparator sc = new UTF16.StringComparator(true,false,0);
1580         for (String item1 : tests) {
1581             String nonNull1 = item1 == null ? "" : item1;
1582             int count = UTF16.countCodePoint(nonNull1);
1583             int expected = count == 0 || count > 1 ? -1 : nonNull1.codePointAt(0);
1584             assertEquals("codepoint test " + Utility.hex(nonNull1), expected, UTF16.getSingleCodePoint(item1));
1585             if (expected == -1) {
1586                 continue;
1587             }
1588             for (String item2 : tests) {
1589                 String nonNull2 = item2 == null ? "" : item2;
1590                 int scValue = Integer.signum(sc.compare(nonNull1, nonNull2));
1591                 int fValue = Integer.signum(UTF16.compareCodePoint(expected, item2));
1592                 assertEquals("comparison " + Utility.hex(nonNull1) + ", " + Utility.hex(nonNull2), scValue, fValue);
1593             }
1594         }
1595     }
1596 
TestNewString()1597     public void TestNewString() {
1598     final int[] codePoints = {
1599         UCharacter.toCodePoint(UCharacter.MIN_HIGH_SURROGATE, UCharacter.MAX_LOW_SURROGATE),
1600         UCharacter.toCodePoint(UCharacter.MAX_HIGH_SURROGATE, UCharacter.MIN_LOW_SURROGATE),
1601         UCharacter.MAX_HIGH_SURROGATE,
1602         'A',
1603         -1,
1604     };
1605 
1606 
1607     final String cpString = "" +
1608         UCharacter.MIN_HIGH_SURROGATE +
1609         UCharacter.MAX_LOW_SURROGATE +
1610         UCharacter.MAX_HIGH_SURROGATE +
1611         UCharacter.MIN_LOW_SURROGATE +
1612         UCharacter.MAX_HIGH_SURROGATE +
1613         'A';
1614 
1615     final int[][] tests = {
1616         { 0, 1, 0, 2 },
1617         { 0, 2, 0, 4 },
1618         { 1, 1, 2, 2 },
1619         { 1, 2, 2, 3 },
1620         { 1, 3, 2, 4 },
1621         { 2, 2, 4, 2 },
1622         { 2, 3, 0, -1 },
1623         { 4, 5, 0, -1 },
1624         { 3, -1, 0, -1 }
1625     };
1626 
1627      for (int i = 0; i < tests.length; ++i) {
1628         int[] t = tests[i];
1629         int s = t[0];
1630         int c = t[1];
1631         int rs = t[2];
1632         int rc = t[3];
1633 
1634         Exception e = null;
1635         try {
1636         String str = UTF16.newString(codePoints, s, c);
1637         if (rc == -1 || !str.equals(cpString.substring(rs, rs+rc))) {
1638             errln("failed codePoints iter: " + i + " start: " + s + " len: " + c);
1639         }
1640         continue;
1641         }
1642         catch (IndexOutOfBoundsException e1) {
1643         e = e1;
1644         }
1645         catch (IllegalArgumentException e2) {
1646         e = e2;
1647         }
1648         if (rc != -1) {
1649         errln(e.getMessage());
1650         }
1651     }
1652     }
1653 
main(String[] arg)1654     public static void main(String[] arg)
1655     {
1656         try
1657         {
1658         UTF16Test test = new UTF16Test();
1659         test.run(arg);
1660         // test.TestCaseCompare();
1661         }
1662         catch (Exception e)
1663         {
1664         e.printStackTrace();
1665         }
1666     }
1667 
1668 
1669     // private data members ----------------------------------------------
1670 
1671     private final static String INDEXOF_SUPPLEMENTARY_STRING_ =
1672         "\ud841\udc02\u0071\udc02\ud841\u0071\ud841\udc02\u0071\u0072" +
1673         "\ud841\udc02\u0071\ud841\udc02\u0071\udc02\ud841\u0073";
1674     private final static int INDEXOF_SUPPLEMENTARY_CHAR_[] =
1675     {0x71, 0xd841, 0xdc02,
1676      UTF16Util.getRawSupplementary((char)0xd841,
1677                  (char)0xdc02)};
1678     private final static int INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[][] =
1679     {{2, 5, 8, 12, 15},
1680      {4, 17},
1681      {3, 16},
1682      {0, 6, 10, 13}
1683     };
1684     private final static String INDEXOF_SUPPLEMENTARY_STR_ = "\udc02\ud841";
1685     private final static int INDEXOF_SUPPLEMENTARY_STR_INDEX_[] =
1686     {3, 16};
1687 
1688     // private methods ---------------------------------------------------
1689 }
1690 
1691