1 11 package com.ibm.icu.impl; 12 13 import java.io.*; 14 15 import com.ibm.icu.lang.*; 16 17 42 public final class UPropertyAliases implements ICUBinary.Authenticate { 43 44 48 51 private NonContiguousEnumToShort enumToName; 52 53 56 private NameToEnum nameToEnum; 57 58 61 private NonContiguousEnumToShort enumToValue; 62 63 66 private ValueMap valueMapArray[]; 67 68 74 private short nameGroupPool[]; 75 76 79 private String stringPool[]; 80 81 84 87 private static boolean DEBUG = ICUDebug.enabled("pnames"); 88 89 93 private static final byte DATA_FORMAT_ID[] = {'p', 'n', 'a', 'm'}; 94 95 99 private static final byte DATA_FORMAT_VERSION = 1; 100 101 104 private static final String DATA_FILE_NAME = ICUResourceBundle.ICU_BUNDLE+"/pnames.icu"; 105 106 109 private static final int DATA_BUFFER_SIZE = 8192; 110 111 114 119 public UPropertyAliases() throws IOException { 120 121 InputStream is = ICUData.getRequiredStream(DATA_FILE_NAME); 123 BufferedInputStream b = new BufferedInputStream(is, DATA_BUFFER_SIZE); 124 ICUBinary.readHeader(b, DATA_FORMAT_ID, this); 126 DataInputStream d = new DataInputStream(b); 127 128 d.mark(256); 131 132 short enumToName_offset = d.readShort(); 133 short nameToEnum_offset = d.readShort(); 134 short enumToValue_offset = d.readShort(); 135 short total_size = d.readShort(); 136 short valueMap_offset = d.readShort(); 137 short valueMap_count = d.readShort(); 138 short nameGroupPool_offset = d.readShort(); 139 short nameGroupPool_count = d.readShort(); 140 short stringPool_offset = d.readShort(); 141 short stringPool_count = d.readShort(); 142 143 if (DEBUG) { 144 System.out.println( 145 "enumToName_offset=" + enumToName_offset + "\n" + 146 "nameToEnum_offset=" + nameToEnum_offset + "\n" + 147 "enumToValue_offset=" + enumToValue_offset + "\n" + 148 "total_size=" + total_size + "\n" + 149 "valueMap_offset=" + valueMap_offset + "\n" + 150 "valueMap_count=" + valueMap_count + "\n" + 151 "nameGroupPool_offset=" + nameGroupPool_offset + "\n" + 152 "nameGroupPool_count=" + nameGroupPool_count + "\n" + 153 "stringPool_offset=" + stringPool_offset + "\n" + 154 "stringPool_count=" + stringPool_count); 155 } 156 157 byte raw[] = new byte[total_size]; 162 d.reset(); 163 d.readFully(raw); 164 d.close(); 165 166 Builder builder = new Builder(raw); 167 168 stringPool = builder.readStringPool(stringPool_offset, 169 stringPool_count); 170 171 nameGroupPool = builder.readNameGroupPool(nameGroupPool_offset, 172 nameGroupPool_count); 173 174 builder.setupValueMap_map(valueMap_offset, valueMap_count); 175 176 181 builder.seek(enumToName_offset); 182 enumToName = new NonContiguousEnumToShort(builder); 183 builder.nameGroupOffsetToIndex(enumToName.offsetArray); 184 185 builder.seek(nameToEnum_offset); 186 nameToEnum = new NameToEnum(builder); 187 188 builder.seek(enumToValue_offset); 189 enumToValue = new NonContiguousEnumToShort(builder); 190 builder.valueMapOffsetToIndex(enumToValue.offsetArray); 191 192 valueMapArray = new ValueMap[valueMap_count]; 193 for (int i=0; i<valueMap_count; ++i) { 194 builder.seek(builder.valueMap_map[i]); 196 valueMapArray[i] = new ValueMap(builder); 197 } 198 199 builder.close(); 200 } 201 202 205 210 public String getPropertyName(int property, 211 int nameChoice) { 212 short nameGroupIndex = enumToName.getShort(property); 213 return chooseNameInGroup(nameGroupIndex, nameChoice); 214 } 215 216 219 public int getPropertyEnum(String propertyAlias) { 220 return nameToEnum.getEnum(propertyAlias); 221 } 222 223 228 public String getPropertyValueName(int property, 229 int value, 230 int nameChoice) { 231 ValueMap vm = getValueMap(property); 232 short nameGroupIndex = vm.enumToName.getShort(value); 233 return chooseNameInGroup(nameGroupIndex, nameChoice); 234 } 235 236 240 public int getPropertyValueEnum(int property, 241 String valueAlias) { 242 ValueMap vm = getValueMap(property); 243 return vm.nameToEnum.getEnum(valueAlias); 244 } 245 246 249 252 private class ValueMap { 253 254 257 EnumToShort enumToName; 259 262 NameToEnum nameToEnum; 263 264 ValueMap(Builder b) throws IOException { 265 short enumToName_offset = b.readShort(); 266 short ncEnumToName_offset = b.readShort(); 267 short nameToEnum_offset = b.readShort(); 268 if (enumToName_offset != 0) { 269 b.seek(enumToName_offset); 270 ContiguousEnumToShort x = new ContiguousEnumToShort(b); 271 b.nameGroupOffsetToIndex(x.offsetArray); 272 enumToName = x; 273 } else { 274 b.seek(ncEnumToName_offset); 275 NonContiguousEnumToShort x = new NonContiguousEnumToShort(b); 276 b.nameGroupOffsetToIndex(x.offsetArray); 277 enumToName = x; 278 } 279 b.seek(nameToEnum_offset); 280 nameToEnum = new NameToEnum(b); 281 } 282 } 283 284 287 private interface EnumToShort { 288 short getShort(int enumProbe); 289 } 290 291 295 private static class ContiguousEnumToShort implements EnumToShort { 296 int enumStart; 297 int enumLimit; 298 short offsetArray[]; 299 300 public short getShort(int enumProbe) { 301 if (enumProbe < enumStart || enumProbe >= enumLimit) { 302 throw new IllegalArgumentException ("Invalid enum. enumStart = " +enumStart + 303 " enumLimit = " + enumLimit + 304 " enumProbe = " + enumProbe ); 305 } 306 return offsetArray[enumProbe - enumStart]; 307 } 308 309 ContiguousEnumToShort(ICUBinaryStream s) throws IOException { 310 enumStart = s.readInt(); 311 enumLimit = s.readInt(); 312 int count = enumLimit - enumStart; 313 offsetArray = new short[count]; 314 for (int i=0; i<count; ++i) { 315 offsetArray[i] = s.readShort(); 316 } 317 } 318 } 319 320 324 private static class NonContiguousEnumToShort implements EnumToShort { 325 int enumArray[]; 326 short offsetArray[]; 327 328 public short getShort(int enumProbe) { 329 for (int i=0; i<enumArray.length; ++i) { 330 if (enumArray[i] < enumProbe) continue; 331 if (enumArray[i] > enumProbe) break; 332 return offsetArray[i]; 333 } 334 throw new IllegalArgumentException ("Invalid enum"); 335 } 336 337 NonContiguousEnumToShort(ICUBinaryStream s) throws IOException { 338 int i; 339 int count = s.readInt(); 340 enumArray = new int[count]; 341 offsetArray = new short[count]; 342 for (i=0; i<count; ++i) { 343 enumArray[i] = s.readInt(); 344 } 345 for (i=0; i<count; ++i) { 346 offsetArray[i] = s.readShort(); 347 } 348 } 349 } 350 351 354 private class NameToEnum { 355 int enumArray[]; 356 short nameArray[]; 357 358 int getEnum(String nameProbe) { 359 for (int i=0; i<nameArray.length; ++i) { 360 int c = UPropertyAliases.compare(nameProbe, 361 stringPool[nameArray[i]]); 362 if (c > 0) continue; 363 if (c < 0) break; 364 return enumArray[i]; 365 } 366 throw new IllegalArgumentException ("Invalid name: " + nameProbe); 367 } 368 369 NameToEnum(Builder b) throws IOException { 370 int i; 371 int count = b.readInt(); 372 enumArray = new int[count]; 373 nameArray = new short[count]; 374 for (i=0; i<count; ++i) { 375 enumArray[i] = b.readInt(); 376 } 377 for (i=0; i<count; ++i) { 378 nameArray[i] = b.stringOffsetToIndex(b.readShort()); 379 } 380 } 381 } 382 383 386 391 public static int compare(String stra, String strb) { 392 int istra=0, istrb=0, rc; 395 int cstra=0, cstrb=0; 396 for (;;) { 397 398 while (istra<stra.length()) { 399 cstra = stra.charAt(istra); 400 switch (cstra) { 401 case '-': case '_': case ' ': case '\t': 402 case '\n': case 0xb: case '\f': case '\r': 403 ++istra; 404 continue; 405 } 406 break; 407 } 408 409 while (istrb<strb.length()) { 410 cstrb = strb.charAt(istrb); 411 switch (cstrb) { 412 case '-': case '_': case ' ': case '\t': 413 case '\n': case 0xb: case '\f': case '\r': 414 ++istrb; 415 continue; 416 } 417 break; 418 } 419 420 421 boolean endstra = istra==stra.length(); 422 boolean endstrb = istrb==strb.length(); 423 if (endstra) { 424 if (endstrb) return 0; 425 cstra = 0; 426 } else if (endstrb) { 427 cstrb = 0; 428 } 429 430 rc = UCharacter.toLowerCase(cstra) - UCharacter.toLowerCase(cstrb); 431 if (rc != 0) { 432 return rc; 433 } 434 435 ++istra; 436 ++istrb; 437 } 438 } 439 440 444 private String chooseNameInGroup(short nameGroupIndex, int nameChoice) { 445 if (nameChoice < 0) { 446 throw new IllegalArgumentException ("Invalid name choice"); 447 } 448 while (nameChoice-- > 0) { 449 if (nameGroupPool[nameGroupIndex++] < 0) { 450 throw new IllegalArgumentException ("Invalid name choice"); 451 } 452 } 453 short a = nameGroupPool[nameGroupIndex]; 454 return stringPool[(a < 0) ? -a : a]; 455 } 456 457 460 private ValueMap getValueMap(int property) { 461 int valueMapIndex = enumToValue.getShort(property); 462 return valueMapArray[valueMapIndex]; 463 } 464 465 468 471 public boolean isDataVersionAcceptable(byte version[]) { 472 return version[0] == DATA_FORMAT_VERSION; 473 } 474 475 478 483 static class Builder extends ICUBinaryStream { 484 485 489 private short stringPool_map[]; 490 491 private short valueMap_map[]; 492 493 private short nameGroup_map[]; 494 495 public Builder(byte raw[]) { 496 super(raw); 497 } 498 499 503 public void setupValueMap_map(short offset, short count) { 504 valueMap_map = new short[count]; 505 for (int i=0; i<count; ++i) { 506 valueMap_map[i] = (short) (offset + i * 6); 508 } 509 } 510 511 515 public String [] readStringPool(short offset, short count) 516 throws IOException { 517 seek(offset); 518 String stringPool[] = new String [count + 1]; 522 stringPool_map = new short[count + 1]; 523 short pos = offset; 524 StringBuffer buf = new StringBuffer (); 525 stringPool_map[0] = 0; 526 for (int i=1; i<=count; ++i) { 527 buf.setLength(0); 528 for (;;) { 529 char c = (char) readUnsignedByte(); 531 if (c == 0) break; 532 buf.append(c); 533 } 534 stringPool_map[i] = pos; 535 stringPool[i] = buf.toString(); 536 pos += stringPool[i].length() + 1; 537 } 538 if (DEBUG) { 539 System.out.println("read stringPool x " + count + 540 ": " + stringPool[1] + ", " + 541 stringPool[2] + ", " + 542 stringPool[3] + ",..."); 543 } 544 return stringPool; 545 } 546 547 551 public short[] readNameGroupPool(short offset, short count) 552 throws IOException { 553 seek(offset); 559 short pos = offset; 560 short nameGroupPool[] = new short[count]; 561 nameGroup_map = new short[count]; 562 for (int i=0; i<count; ++i) { 563 nameGroup_map[i] = pos; 564 nameGroupPool[i] = stringOffsetToIndex(readShort()); 565 pos += 2; 566 } 567 if (DEBUG) { 568 System.out.println("read nameGroupPool x " + count + 569 ": " + nameGroupPool[0] + ", " + 570 nameGroupPool[1] + ", " + 571 nameGroupPool[2] + ",..."); 572 } 573 return nameGroupPool; 574 } 575 576 580 private short stringOffsetToIndex(short offset) { 581 int probe = offset; 582 if (probe < 0) probe = -probe; 583 for (int i=0; i<stringPool_map.length; ++i) { 584 if (stringPool_map[i] == probe) { 585 return (short) ((offset < 0) ? -i : i); 586 } 587 } 588 throw new IllegalStateException ("Can't map string pool offset " + 589 offset + " to index"); 590 } 591 592 597 private void stringOffsetToIndex(short array[]) { 599 for (int i=0; i<array.length; ++i) { 600 array[i] = stringOffsetToIndex(array[i]); 601 } 602 } 603 605 609 private short valueMapOffsetToIndex(short offset) { 610 for (short i=0; i<valueMap_map.length; ++i) { 611 if (valueMap_map[i] == offset) { 612 return i; 613 } 614 } 615 throw new IllegalStateException ("Can't map value map offset " + 616 offset + " to index"); 617 } 618 619 624 private void valueMapOffsetToIndex(short array[]) { 625 for (int i=0; i<array.length; ++i) { 626 array[i] = valueMapOffsetToIndex(array[i]); 627 } 628 } 629 630 634 private short nameGroupOffsetToIndex(short offset) { 635 for (short i=0; i<nameGroup_map.length; ++i) { 636 if (nameGroup_map[i] == offset) { 637 return i; 638 } 639 } 640 throw new RuntimeException ("Can't map name group offset " + offset + 641 " to index"); 642 } 643 644 649 private void nameGroupOffsetToIndex(short array[]) { 650 for (int i=0; i<array.length; ++i) { 651 array[i] = nameGroupOffsetToIndex(array[i]); 652 } 653 } 654 } 655 } 656 | Popular Tags |