1 19 20 package com.ibm.icu.impl; 21 22 import java.io.InputStream ; 23 import java.io.DataInputStream ; 24 import java.io.BufferedInputStream ; 25 import java.io.IOException ; 26 27 import com.ibm.icu.util.RangeValueIterator; 28 import com.ibm.icu.util.ULocale; 29 30 import com.ibm.icu.text.UTF16; 31 import com.ibm.icu.text.UnicodeSet; 32 33 import com.ibm.icu.lang.UCharacter; 34 35 public final class UCaseProps { 36 38 public UCaseProps() throws IOException { 40 InputStream is=ICUData.getRequiredStream(ICUResourceBundle.ICU_BUNDLE+"/"+DATA_FILE_NAME); 41 BufferedInputStream b=new BufferedInputStream (is, 4096 ); 42 readData(b); 43 b.close(); 44 is.close(); 45 } 46 47 private final void readData(InputStream is) throws IOException { 48 DataInputStream inputStream=new DataInputStream (is); 49 50 unicodeVersion=ICUBinary.readHeader(inputStream, FMT, new IsAcceptable()); 52 53 int i, count; 55 count=inputStream.readInt(); 56 if(count<IX_INDEX_TOP) { 57 throw new IOException ("indexes[0] too small in "+DATA_FILE_NAME); 58 } 59 indexes=new int[count]; 60 61 indexes[0]=count; 62 for(i=1; i<count; ++i) { 63 indexes[i]=inputStream.readInt(); 64 } 65 66 trie=new CharTrie(inputStream, null); 68 69 count=indexes[IX_EXC_LENGTH]; 71 if(count>0) { 72 exceptions=new char[count]; 73 for(i=0; i<count; ++i) { 74 exceptions[i]=inputStream.readChar(); 75 } 76 } 77 78 count=indexes[IX_UNFOLD_LENGTH]; 80 if(count>0) { 81 unfold=new char[count]; 82 for(i=0; i<count; ++i) { 83 unfold[i]=inputStream.readChar(); 84 } 85 } 86 } 87 88 private final class IsAcceptable implements ICUBinary.Authenticate { 90 public boolean isDataVersionAcceptable(byte version[]) { 91 formatVersion=version; 92 return version[0]==1 && 93 version[2]==Trie.INDEX_STAGE_1_SHIFT_ && version[3]==Trie.INDEX_STAGE_2_SHIFT_; 94 } 95 } 96 97 private static UCaseProps gCsp=null; 99 100 public static final synchronized UCaseProps getSingleton() throws IOException { 102 if(gCsp==null) { 103 gCsp=new UCaseProps(); 104 } 105 return gCsp; 106 } 107 108 private static UCaseProps gCspDummy=null; 110 111 private UCaseProps(boolean makeDummy) { formatVersion=new byte[] { 1, 0, Trie.INDEX_STAGE_1_SHIFT_, Trie.INDEX_STAGE_2_SHIFT_ }; 113 unicodeVersion=new byte[] { 2, 0, 0, 0 }; 114 indexes=new int[IX_TOP]; 115 indexes[0]=IX_TOP; 116 trie=new CharTrie(0, 0, null); } 118 119 125 public static final synchronized UCaseProps getDummy() { 126 if(gCspDummy==null) { 127 gCspDummy=new UCaseProps(true); 128 } 129 return gCspDummy; 130 } 131 132 134 public final void addPropertyStarts(UnicodeSet set) { 135 136 TrieIterator iter=new TrieIterator(trie); 137 RangeValueIterator.Element element=new RangeValueIterator.Element(); 138 139 while(iter.next(element)){ 140 set.add(element.start); 141 } 142 143 144 145 146 147 151 } 152 153 private static final int getExceptionsOffset(int props) { 155 return props>>EXC_SHIFT; 156 } 157 158 private static final boolean propsHasException(int props) { 159 return (props&EXCEPTION)!=0; 160 } 161 162 163 private static final byte flagsOffset[]={ 164 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 165 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 166 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 167 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 168 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 169 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 170 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 171 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 172 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 173 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 174 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 175 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 176 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 177 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 178 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 179 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 180 }; 181 182 private static final boolean hasSlot(int flags, int index) { 183 return (flags&(1<<index))!=0; 184 } 185 private static final byte slotOffset(int flags, int index) { 186 return flagsOffset[flags&((1<<index)-1)]; 187 } 188 189 198 private final long getSlotValueAndOffset(int excWord, int index, int excOffset) { 199 long value; 200 if((excWord&EXC_DOUBLE_SLOTS)==0) { 201 excOffset+=slotOffset(excWord, index); 202 value=exceptions[excOffset]; 203 } else { 204 excOffset+=2*slotOffset(excWord, index); 205 value=exceptions[excOffset++]; 206 value=(value<<16)|exceptions[excOffset]; 207 } 208 return (long)value|((long)excOffset<<32); 209 } 210 211 212 private final int getSlotValue(int excWord, int index, int excOffset) { 213 int value; 214 if((excWord&EXC_DOUBLE_SLOTS)==0) { 215 excOffset+=slotOffset(excWord, index); 216 value=exceptions[excOffset]; 217 } else { 218 excOffset+=2*slotOffset(excWord, index); 219 value=exceptions[excOffset++]; 220 value=(value<<16)|exceptions[excOffset]; 221 } 222 return value; 223 } 224 225 227 public final int tolower(int c) { 228 int props=trie.getCodePointValue(c); 229 if(!propsHasException(props)) { 230 if(getTypeFromProps(props)>=UPPER) { 231 c+=getDelta(props); 232 } 233 } else { 234 int excOffset=getExceptionsOffset(props); 235 int excWord=exceptions[excOffset++]; 236 if(hasSlot(excWord, EXC_LOWER)) { 237 c=getSlotValue(excWord, EXC_LOWER, excOffset); 238 } 239 } 240 return c; 241 } 242 243 public final int toupper(int c) { 244 int props=trie.getCodePointValue(c); 245 if(!propsHasException(props)) { 246 if(getTypeFromProps(props)==LOWER) { 247 c+=getDelta(props); 248 } 249 } else { 250 int excOffset=getExceptionsOffset(props); 251 int excWord=exceptions[excOffset++]; 252 if(hasSlot(excWord, EXC_UPPER)) { 253 c=getSlotValue(excWord, EXC_UPPER, excOffset); 254 } 255 } 256 return c; 257 } 258 259 public final int totitle(int c) { 260 int props=trie.getCodePointValue(c); 261 if(!propsHasException(props)) { 262 if(getTypeFromProps(props)==LOWER) { 263 c+=getDelta(props); 264 } 265 } else { 266 int excOffset=getExceptionsOffset(props); 267 int excWord=exceptions[excOffset++]; 268 int index; 269 if(hasSlot(excWord, EXC_TITLE)) { 270 index=EXC_TITLE; 271 } else if(hasSlot(excWord, EXC_UPPER)) { 272 index=EXC_UPPER; 273 } else { 274 return c; 275 } 276 c=getSlotValue(excWord, index, excOffset); 277 } 278 return c; 279 } 280 281 290 public final void addCaseClosure(int c, UnicodeSet set) { 291 298 299 switch(c) { 300 case 0x49: 301 302 set.add(0x69); 303 return; 304 case 0x69: 305 set.add(0x49); 306 return; 307 case 0x130: 308 309 set.add(iDot); 310 return; 311 case 0x131: 312 313 return; 314 default: 315 316 break; 317 } 318 319 int props=trie.getCodePointValue(c); 320 if(!propsHasException(props)) { 321 if(getTypeFromProps(props)!=NONE) { 322 323 int delta=getDelta(props); 324 if(delta!=0) { 325 set.add(c+delta); 326 } 327 } 328 } else { 329 333 int excOffset0, excOffset=getExceptionsOffset(props); 334 int closureOffset; 335 int excWord=exceptions[excOffset++]; 336 int index, closureLength, fullLength, length; 337 338 excOffset0=excOffset; 339 340 341 for(index=EXC_LOWER; index<=EXC_TITLE; ++index) { 342 if(hasSlot(excWord, index)) { 343 excOffset=excOffset0; 344 c=getSlotValue(excWord, index, excOffset); 345 set.add(c); 346 } 347 } 348 349 350 if(hasSlot(excWord, EXC_CLOSURE)) { 351 excOffset=excOffset0; 352 long value=getSlotValueAndOffset(excWord, EXC_CLOSURE, excOffset); 353 closureLength=(int)value&CLOSURE_MAX_LENGTH; 354 closureOffset=(int)(value>>32)+1; 355 } else { 356 closureLength=0; 357 closureOffset=0; 358 } 359 360 361 if(hasSlot(excWord, EXC_FULL_MAPPINGS)) { 362 excOffset=excOffset0; 363 long value=getSlotValueAndOffset(excWord, EXC_FULL_MAPPINGS, excOffset); 364 fullLength=(int)value; 365 366 367 excOffset=(int)(value>>32)+1; 368 369 fullLength&=0xffff; 370 371 372 excOffset+=fullLength&FULL_LOWER; 373 fullLength>>=4; 374 375 376 length=fullLength&0xf; 377 if(length!=0) { 378 set.add(new String (exceptions, excOffset, length)); 379 excOffset+=length; 380 } 381 382 383 fullLength>>=4; 384 excOffset+=fullLength&0xf; 385 fullLength>>=4; 386 excOffset+=fullLength; 387 388 closureOffset=excOffset; 389 } 390 391 392 for(index=0; index<closureLength; index+=UTF16.getCharCount(c)) { 393 c=UTF16.charAt(exceptions, closureOffset, exceptions.length, index); 394 set.add(c); 395 } 396 } 397 } 398 399 403 private final int strcmpMax(String s, int unfoldOffset, int max) { 404 int i1, length, c1, c2; 405 406 length=s.length(); 407 max-=length; 408 i1=0; 409 do { 410 c1=s.charAt(i1++); 411 c2=unfold[unfoldOffset++]; 412 if(c2==0) { 413 return 1; 414 } 415 c1-=c2; 416 if(c1!=0) { 417 return c1; 418 } 419 } while(--length>0); 420 421 422 if(max==0 || unfold[unfoldOffset]==0) { 423 return 0; 424 } else { 425 return -max; 426 } 427 } 428 429 440 public final boolean addStringCaseClosure(String s, UnicodeSet set) { 441 int i, length, start, limit, result, unfoldOffset, unfoldRows, unfoldRowWidth, unfoldStringWidth; 442 443 if(unfold==null || s==null) { 444 return false; 445 } 446 length=s.length(); 447 if(length<=1) { 448 449 455 return false; 456 } 457 458 unfoldRows=unfold[UNFOLD_ROWS]; 459 unfoldRowWidth=unfold[UNFOLD_ROW_WIDTH]; 460 unfoldStringWidth=unfold[UNFOLD_STRING_WIDTH]; 461 463 if(length>unfoldStringWidth) { 464 465 return false; 466 } 467 468 469 start=0; 470 limit=unfoldRows; 471 while(start<limit) { 472 i=(start+limit)/2; 473 unfoldOffset=((i+1)*unfoldRowWidth); result=strcmpMax(s, unfoldOffset, unfoldStringWidth); 475 476 if(result==0) { 477 478 int c; 479 480 for(i=unfoldStringWidth; i<unfoldRowWidth && unfold[unfoldOffset+i]!=0; i+=UTF16.getCharCount(c)) { 481 c=UTF16.charAt(unfold, unfoldOffset, unfold.length, i); 482 set.add(c); 483 addCaseClosure(c, set); 484 } 485 return true; 486 } else if(result<0) { 487 limit=i; 488 } else { 489 start=i+1; 490 } 491 } 492 493 return false; 494 } 495 496 497 public final int getType(int c) { 498 return getTypeFromProps(trie.getCodePointValue(c)); 499 } 500 501 502 public final int getTypeOrIgnorable(int c) { 503 int props=trie.getCodePointValue(c); 504 int type=getTypeFromProps(props); 505 if(type!=NONE) { 506 return type; 507 } else if( 508 c==0x307 || 509 (props&(EXCEPTION|CASE_IGNORABLE))==CASE_IGNORABLE 510 ) { 511 return -1; 512 } else { 513 return 0; 514 } 515 } 516 517 518 public final int getDotType(int c) { 519 int props=trie.getCodePointValue(c); 520 if(!propsHasException(props)) { 521 return props&DOT_MASK; 522 } else { 523 return (exceptions[getExceptionsOffset(props)]>>EXC_DOT_SHIFT)&DOT_MASK; 524 } 525 } 526 527 public final boolean isSoftDotted(int c) { 528 return getDotType(c)==SOFT_DOTTED; 529 } 530 531 public final boolean isCaseSensitive(int c) { 532 return (trie.getCodePointValue(c)&SENSITIVE)!=0; 533 } 534 535 537 614 615 627 public interface ContextIterator { 628 635 public void reset(int dir); 636 641 public int next(); 642 } 643 644 658 public static final int MAX_STRING_LENGTH=0x1f; 659 660 private static final int LOC_UNKNOWN=0; 661 private static final int LOC_ROOT=1; 662 private static final int LOC_TURKISH=2; 663 private static final int LOC_LITHUANIAN=3; 664 665 669 private static final int getCaseLocale(ULocale locale, int[] locCache) { 670 int result; 671 672 if(locCache!=null && (result=locCache[0])!=LOC_UNKNOWN) { 673 return result; 674 } 675 676 result=LOC_ROOT; 677 678 String language=locale.getLanguage(); 679 if(language.equals("tr") || language.equals("tur") || language.equals("az") || language.equals("aze")) { 680 result=LOC_TURKISH; 681 } else if(language.equals("lt") || language.equals("lit")) { 682 result=LOC_LITHUANIAN; 683 } 684 685 if(locCache!=null) { 686 locCache[0]=result; 687 } 688 return result; 689 } 690 691 692 private final boolean isFollowedByCasedLetter(ContextIterator iter, int dir) { 693 int c; 694 int props; 695 696 if(iter==null) { 697 return false; 698 } 699 700 for(iter.reset(dir); (c=iter.next())>=0;) { 701 props=trie.getCodePointValue(c); 702 if(getTypeFromProps(props)!=NONE) { 703 return true; 704 } else if(c==0x307 || (props&(EXCEPTION|CASE_IGNORABLE))==CASE_IGNORABLE) { 705 706 } else { 707 return false; 708 } 709 } 710 711 return false; 712 } 713 714 715 private final boolean isPrecededBySoftDotted(ContextIterator iter) { 716 int c; 717 int dotType; 718 719 if(iter==null) { 720 return false; 721 } 722 723 for(iter.reset(-1); (c=iter.next())>=0;) { 724 dotType=getDotType(c); 725 if(dotType==SOFT_DOTTED) { 726 return true; 727 } else if(dotType!=OTHER_ACCENT) { 728 return false; 729 } 730 } 731 732 return false; 733 } 734 735 768 769 770 private final boolean isPrecededBy_I(ContextIterator iter) { 771 int c; 772 int dotType; 773 774 if(iter==null) { 775 return false; 776 } 777 778 for(iter.reset(-1); (c=iter.next())>=0;) { 779 if(c==0x49) { 780 return true; 781 } 782 dotType=getDotType(c); 783 if(dotType!=OTHER_ACCENT) { 784 return false; 785 } 786 } 787 788 return false; 789 } 790 791 792 private final boolean isFollowedByMoreAbove(ContextIterator iter) { 793 int c; 794 int dotType; 795 796 if(iter==null) { 797 return false; 798 } 799 800 for(iter.reset(1); (c=iter.next())>=0;) { 801 dotType=getDotType(c); 802 if(dotType==ABOVE) { 803 return true; 804 } else if(dotType!=OTHER_ACCENT) { 805 return false; 806 } 807 } 808 809 return false; 810 } 811 812 813 private final boolean isFollowedByDotAbove(ContextIterator iter) { 814 int c; 815 int dotType; 816 817 if(iter==null) { 818 return false; 819 } 820 821 for(iter.reset(1); (c=iter.next())>=0; ) { 822 if(c==0x307) { 823 return true; 824 } 825 dotType=getDotType(c); 826 if(dotType!=OTHER_ACCENT) { 827 return false; 828 } 829 } 830 831 return false; 832 } 833 834 private static final String 835 iDot= "i\u0307", 836 jDot= "j\u0307", 837 iOgonekDot= "\u012f\u0307", 838 iDotGrave= "i\u0307\u0300", 839 iDotAcute= "i\u0307\u0301", 840 iDotTilde= "i\u0307\u0303"; 841 842 860 public final int toFullLower(int c, ContextIterator iter, 861 StringBuffer out, 862 ULocale locale, int[] locCache) { 863 int result, props; 864 865 result=c; 866 props=trie.getCodePointValue(c); 867 if(!propsHasException(props)) { 868 if(getTypeFromProps(props)>=UPPER) { 869 result=c+getDelta(props); 870 } 871 } else { 872 int excOffset=getExceptionsOffset(props), excOffset2; 873 int excWord=exceptions[excOffset++]; 874 int full; 875 876 excOffset2=excOffset; 877 878 if((excWord&EXC_CONDITIONAL_SPECIAL)!=0) { 879 880 int loc=getCaseLocale(locale, locCache); 881 882 888 if( loc==LOC_LITHUANIAN && 889 890 (((c==0x49 || c==0x4a || c==0x12e) && 891 isFollowedByMoreAbove(iter)) || 892 893 (c==0xcc || c==0xcd || c==0x128)) 894 ) { 895 911 switch(c) { 912 case 0x49: 913 out.append(iDot); 914 return 2; 915 case 0x4a: 916 out.append(jDot); 917 return 2; 918 case 0x12e: 919 out.append(iOgonekDot); 920 return 2; 921 case 0xcc: 922 out.append(iDotGrave); 923 return 3; 924 case 0xcd: 925 out.append(iDotAcute); 926 return 3; 927 case 0x128: 928 out.append(iDotTilde); 929 return 3; 930 default: 931 return 0; 932 } 933 934 } else if(loc==LOC_TURKISH && c==0x130) { 935 942 return 0x69; 943 } else if(loc==LOC_TURKISH && c==0x307 && isPrecededBy_I(iter)) { 944 951 return 0; 952 } else if(loc==LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(iter)) { 953 959 return 0x131; 960 } else if(c==0x130) { 961 966 out.append(iDot); 967 return 2; 968 } else if( c==0x3a3 && 969 !isFollowedByCasedLetter(iter, 1) && 970 isFollowedByCasedLetter(iter, -1) 971 ) { 972 973 978 return 0x3c2; 979 } else { 980 981 } 982 } else if(hasSlot(excWord, EXC_FULL_MAPPINGS)) { 983 long value=getSlotValueAndOffset(excWord, EXC_FULL_MAPPINGS, excOffset); 984 full=(int)value&FULL_LOWER; 985 if(full!=0) { 986 987 excOffset=(int)(value>>32)+1; 988 989 990 out.append(new String (exceptions, excOffset, full)); 991 992 993 return full; 994 } 995 } 996 997 if(hasSlot(excWord, EXC_LOWER)) { 998 result=getSlotValue(excWord, EXC_LOWER, excOffset2); 999 } 1000 } 1001 1002 return (result==c) ? ~result : result; 1003 } 1004 1005 1006 private final int toUpperOrTitle(int c, ContextIterator iter, 1007 StringBuffer out, 1008 ULocale locale, int[] locCache, 1009 boolean upperNotTitle) { 1010 int result; 1011 int props; 1012 1013 result=c; 1014 props=trie.getCodePointValue(c); 1015 if(!propsHasException(props)) { 1016 if(getTypeFromProps(props)==LOWER) { 1017 result=c+getDelta(props); 1018 } 1019 } else { 1020 int excOffset=getExceptionsOffset(props), excOffset2; 1021 int excWord=exceptions[excOffset++]; 1022 int full, index; 1023 1024 excOffset2=excOffset; 1025 1026 if((excWord&EXC_CONDITIONAL_SPECIAL)!=0) { 1027 1028 int loc=getCaseLocale(locale, locCache); 1029 1030 if(loc==LOC_TURKISH && c==0x69) { 1031 1042 return 0x130; 1043 } else if(loc==LOC_LITHUANIAN && c==0x307 && isPrecededBySoftDotted(iter)) { 1044 1053 return 0; 1054 } else { 1055 1056 } 1057 } else if(hasSlot(excWord, EXC_FULL_MAPPINGS)) { 1058 long value=getSlotValueAndOffset(excWord, EXC_FULL_MAPPINGS, excOffset); 1059 full=(int)value&0xffff; 1060 1061 1062 excOffset=(int)(value>>32)+1; 1063 1064 1065 excOffset+=full&FULL_LOWER; 1066 full>>=4; 1067 excOffset+=full&0xf; 1068 full>>=4; 1069 1070 if(upperNotTitle) { 1071 full&=0xf; 1072 } else { 1073 1074 excOffset+=full&0xf; 1075 full=(full>>4)&0xf; 1076 } 1077 1078 if(full!=0) { 1079 1080 out.append(new String (exceptions, excOffset, full)); 1081 1082 1083 return full; 1084 } 1085 } 1086 1087 if(!upperNotTitle && hasSlot(excWord, EXC_TITLE)) { 1088 index=EXC_TITLE; 1089 } else if(hasSlot(excWord, EXC_UPPER)) { 1090 1091 index=EXC_UPPER; 1092 } else { 1093 return ~c; 1094 } 1095 result=getSlotValue(excWord, index, excOffset2); 1096 } 1097 1098 return (result==c) ? ~result : result; 1099 } 1100 1101 public final int toFullUpper(int c, ContextIterator iter, 1102 StringBuffer out, 1103 ULocale locale, int[] locCache) { 1104 return toUpperOrTitle(c, iter, out, locale, locCache, true); 1105 } 1106 1107 public final int toFullTitle(int c, ContextIterator iter, 1108 StringBuffer out, 1109 ULocale locale, int[] locCache) { 1110 return toUpperOrTitle(c, iter, out, locale, locCache, false); 1111 } 1112 1113 1114 1115 1153 1154 1159 private static final int FOLD_CASE_OPTIONS_MASK = 0xff; 1160 1161 1162 public final int fold(int c, int options) { 1163 int props=trie.getCodePointValue(c); 1164 if(!propsHasException(props)) { 1165 if(getTypeFromProps(props)>=UPPER) { 1166 c+=getDelta(props); 1167 } 1168 } else { 1169 int excOffset=getExceptionsOffset(props); 1170 int excWord=exceptions[excOffset++]; 1171 int index; 1172 if((excWord&EXC_CONDITIONAL_FOLD)!=0) { 1173 1174 if((options&FOLD_CASE_OPTIONS_MASK)==UCharacter.FOLD_CASE_DEFAULT) { 1175 1176 if(c==0x49) { 1177 1178 return 0x69; 1179 } else if(c==0x130) { 1180 1181 return c; 1182 } 1183 } else { 1184 1185 if(c==0x49) { 1186 1187 return 0x131; 1188 } else if(c==0x130) { 1189 1190 return 0x69; 1191 } 1192 } 1193 } 1194 if(hasSlot(excWord, EXC_FOLD)) { 1195 index=EXC_FOLD; 1196 } else if(hasSlot(excWord, EXC_LOWER)) { 1197 index=EXC_LOWER; 1198 } else { 1199 return c; 1200 } 1201 c=getSlotValue(excWord, index, excOffset); 1202 } 1203 return c; 1204 } 1205 1206 1220 1221 public final int toFullFolding(int c, StringBuffer out, int options) { 1222 int result; 1223 int props; 1224 1225 result=c; 1226 props=trie.getCodePointValue(c); 1227 if(!propsHasException(props)) { 1228 if(getTypeFromProps(props)>=UPPER) { 1229 result=c+getDelta(props); 1230 } 1231 } else { 1232 int excOffset=getExceptionsOffset(props), excOffset2; 1233 int excWord=exceptions[excOffset++]; 1234 int full, index; 1235 1236 excOffset2=excOffset; 1237 1238 if((excWord&EXC_CONDITIONAL_FOLD)!=0) { 1239 1240 if((options&FOLD_CASE_OPTIONS_MASK)==UCharacter.FOLD_CASE_DEFAULT) { 1241 1242 if(c==0x49) { 1243 1244 return 0x69; 1245 } else if(c==0x130) { 1246 1247 out.append(iDot); 1248 return 2; 1249 } 1250 } else { 1251 1252 if(c==0x49) { 1253 1254 return 0x131; 1255 } else if(c==0x130) { 1256 1257 return 0x69; 1258 } 1259 } 1260 } else if(hasSlot(excWord, EXC_FULL_MAPPINGS)) { 1261 long value=getSlotValueAndOffset(excWord, EXC_FULL_MAPPINGS, excOffset); 1262 full=(int)value&0xffff; 1263 1264 1265 excOffset=(int)(value>>32)+1; 1266 1267 1268 excOffset+=full&FULL_LOWER; 1269 full=(full>>4)&0xf; 1270 1271 if(full!=0) { 1272 1273 out.append(new String (exceptions, excOffset, full)); 1274 1275 1276 return full; 1277 } 1278 } 1279 1280 if(hasSlot(excWord, EXC_FOLD)) { 1281 index=EXC_FOLD; 1282 } else if(hasSlot(excWord, EXC_LOWER)) { 1283 index=EXC_LOWER; 1284 } else { 1285 return ~c; 1286 } 1287 result=getSlotValue(excWord, index, excOffset2); 1288 } 1289 1290 return (result==c) ? ~result : result; 1291 } 1292 1293 private int indexes[]; 1295 private char exceptions[]; 1296 private char unfold[]; 1297 1298 private CharTrie trie; 1299 private byte formatVersion[]; 1300 private byte unicodeVersion[]; 1301 1302 private static final String DATA_NAME="ucase"; 1304 private static final String DATA_TYPE="icu"; 1305 private static final String DATA_FILE_NAME=DATA_NAME+"."+DATA_TYPE; 1306 1307 1308 private static final byte FMT[]={ 0x63, 0x41, 0x53, 0x45 }; 1309 1310 1311 private static final int IX_INDEX_TOP=0; 1312 private static final int IX_LENGTH=1; 1313 private static final int IX_TRIE_SIZE=2; 1314 private static final int IX_EXC_LENGTH=3; 1315 private static final int IX_UNFOLD_LENGTH=4; 1316 1317 private static final int IX_MAX_FULL_LENGTH=15; 1318 private static final int IX_TOP=16; 1319 1320 1322 1323 public static final int TYPE_MASK=3; 1324 public static final int NONE=0; 1325 public static final int LOWER=1; 1326 public static final int UPPER=2; 1327 public static final int TITLE=3; 1328 1329 private static final int getTypeFromProps(int props) { 1330 return props&TYPE_MASK; 1331 } 1332 1333 private static final int SENSITIVE= 4; 1334 private static final int EXCEPTION= 8; 1335 1336 private static final int DOT_MASK= 0x30; 1337 private static final int NO_DOT= 0; 1338 private static final int SOFT_DOTTED= 0x10; 1339 private static final int ABOVE= 0x20; 1340 private static final int OTHER_ACCENT= 0x30; 1341 1342 1343 private static final int DELTA_SHIFT= 6; 1344 private static final int DELTA_MASK= 0xffc0; 1345 private static final int MAX_DELTA= 0x1ff; 1346 private static final int MIN_DELTA= (-MAX_DELTA-1); 1347 1348 private static final int getDelta(int props) { 1349 return (short)props>>DELTA_SHIFT; 1350 } 1351 1352 1353 private static final int CASE_IGNORABLE=0x40; 1354 1355 1356 private static final int EXC_SHIFT= 4; 1357 private static final int EXC_MASK= 0xfff0; 1358 private static final int MAX_EXCEPTIONS=0x1000; 1359 1360 1361 1362 1363 private static final int EXC_LOWER=0; 1364 private static final int EXC_FOLD=1; 1365 private static final int EXC_UPPER=2; 1366 private static final int EXC_TITLE=3; 1367 private static final int EXC_4=4; 1368 private static final int EXC_5=5; 1369 private static final int EXC_CLOSURE=6; 1370 private static final int EXC_FULL_MAPPINGS=7; 1371 private static final int EXC_ALL_SLOTS=8; 1372 1373 1374 private static final int EXC_DOUBLE_SLOTS= 0x100; 1375 1376 1377 1378 1379 private static final int EXC_DOT_SHIFT=8; 1380 1381 1382 private static final int EXC_DOT_MASK= 0x3000; 1383 private static final int EXC_NO_DOT= 0; 1384 private static final int EXC_SOFT_DOTTED= 0x1000; 1385 private static final int EXC_ABOVE= 0x2000; 1386 private static final int EXC_OTHER_ACCENT= 0x3000; 1387 1388 1389 private static final int EXC_CONDITIONAL_SPECIAL= 0x4000; 1390 private static final int EXC_CONDITIONAL_FOLD= 0x8000; 1391 1392 1393 private static final int FULL_LOWER= 0xf; 1394 private static final int FULL_FOLDING= 0xf0; 1395 private static final int FULL_UPPER= 0xf00; 1396 private static final int FULL_TITLE= 0xf000; 1397 1398 1399 private static final int FULL_MAPPINGS_MAX_LENGTH=4*0xf; 1400 private static final int CLOSURE_MAX_LENGTH=0xf; 1401 1402 1403 private static final int UNFOLD_ROWS=0; 1404 private static final int UNFOLD_ROW_WIDTH=1; 1405 private static final int UNFOLD_STRING_WIDTH=2; 1406} 1407 | Popular Tags |