1 /* 2 ********************************************************************** 3 * Copyright (c) 2004-2014, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ********************************************************************** 6 * Author: Alan Liu 7 * Created: April 26, 2004 8 * Since: ICU 3.0 9 ********************************************************************** 10 */ 11 #include "utypeinfo.h" // for 'typeid' to work 12 13 #include "unicode/measunit.h" 14 15 #if !UCONFIG_NO_FORMATTING 16 17 #include "unicode/uenum.h" 18 #include "ustrenum.h" 19 #include "cstring.h" 20 #include "uassert.h" 21 22 #define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0])) 23 24 U_NAMESPACE_BEGIN 25 26 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureUnit) 27 28 static const int32_t gOffsets[] = { 29 0, 30 1, 31 4, 32 10, 33 270, 34 278, 35 288, 36 292, 37 295, 38 298, 39 301, 40 303, 41 306 42 }; 43 44 static const int32_t gIndexes[] = { 45 0, 46 1, 47 4, 48 10, 49 10, 50 18, 51 28, 52 32, 53 35, 54 38, 55 41, 56 43, 57 46 58 }; 59 60 static const char * const gTypes[] = { 61 "acceleration", 62 "angle", 63 "area", 64 "currency", 65 "duration", 66 "length", 67 "mass", 68 "power", 69 "pressure", 70 "speed", 71 "temperature", 72 "volume" 73 }; 74 75 static const char * const gSubTypes[] = { 76 "g-force", 77 "arc-minute", 78 "arc-second", 79 "degree", 80 "acre", 81 "hectare", 82 "square-foot", 83 "square-kilometer", 84 "square-meter", 85 "square-mile", 86 "ADP", 87 "AED", 88 "AFA", 89 "AFN", 90 "ALL", 91 "AMD", 92 "ANG", 93 "AOA", 94 "AON", 95 "AOR", 96 "ARA", 97 "ARP", 98 "ARS", 99 "ATS", 100 "AUD", 101 "AWG", 102 "AYM", 103 "AZM", 104 "AZN", 105 "BAD", 106 "BAM", 107 "BBD", 108 "BDT", 109 "BEC", 110 "BEF", 111 "BEL", 112 "BGL", 113 "BGN", 114 "BHD", 115 "BIF", 116 "BMD", 117 "BND", 118 "BOB", 119 "BOV", 120 "BRC", 121 "BRE", 122 "BRL", 123 "BRN", 124 "BRR", 125 "BSD", 126 "BTN", 127 "BWP", 128 "BYB", 129 "BYR", 130 "BZD", 131 "CAD", 132 "CDF", 133 "CHC", 134 "CHE", 135 "CHF", 136 "CHW", 137 "CLF", 138 "CLP", 139 "CNY", 140 "COP", 141 "COU", 142 "CRC", 143 "CSD", 144 "CSK", 145 "CUC", 146 "CUP", 147 "CVE", 148 "CYP", 149 "CZK", 150 "DDM", 151 "DEM", 152 "DJF", 153 "DKK", 154 "DOP", 155 "DZD", 156 "ECS", 157 "ECV", 158 "EEK", 159 "EGP", 160 "ERN", 161 "ESA", 162 "ESB", 163 "ESP", 164 "ETB", 165 "EUR", 166 "FIM", 167 "FJD", 168 "FKP", 169 "FRF", 170 "GBP", 171 "GEK", 172 "GEL", 173 "GHC", 174 "GHP", 175 "GHS", 176 "GIP", 177 "GMD", 178 "GNF", 179 "GQE", 180 "GRD", 181 "GTQ", 182 "GWP", 183 "GYD", 184 "HKD", 185 "HNL", 186 "HRD", 187 "HRK", 188 "HTG", 189 "HUF", 190 "IDR", 191 "IEP", 192 "ILS", 193 "INR", 194 "IQD", 195 "IRR", 196 "ISK", 197 "ITL", 198 "JMD", 199 "JOD", 200 "JPY", 201 "KES", 202 "KGS", 203 "KHR", 204 "KMF", 205 "KPW", 206 "KRW", 207 "KWD", 208 "KYD", 209 "KZT", 210 "LAK", 211 "LBP", 212 "LKR", 213 "LRD", 214 "LSL", 215 "LTL", 216 "LTT", 217 "LUC", 218 "LUF", 219 "LUL", 220 "LVL", 221 "LVR", 222 "LYD", 223 "MAD", 224 "MDL", 225 "MGA", 226 "MGF", 227 "MKD", 228 "MLF", 229 "MMK", 230 "MNT", 231 "MOP", 232 "MRO", 233 "MTL", 234 "MUR", 235 "MVR", 236 "MWK", 237 "MXN", 238 "MXV", 239 "MYR", 240 "MZM", 241 "MZN", 242 "NAD", 243 "NGN", 244 "NIO", 245 "NLG", 246 "NOK", 247 "NPR", 248 "NZD", 249 "OMR", 250 "PAB", 251 "PEI", 252 "PEN", 253 "PES", 254 "PGK", 255 "PHP", 256 "PKR", 257 "PLN", 258 "PLZ", 259 "PTE", 260 "PYG", 261 "QAR", 262 "ROL", 263 "RON", 264 "RSD", 265 "RUB", 266 "RUR", 267 "RWF", 268 "SAR", 269 "SBD", 270 "SCR", 271 "SDD", 272 "SDG", 273 "SEK", 274 "SGD", 275 "SHP", 276 "SIT", 277 "SKK", 278 "SLL", 279 "SOS", 280 "SRD", 281 "SRG", 282 "SSP", 283 "STD", 284 "SVC", 285 "SYP", 286 "SZL", 287 "THB", 288 "TJR", 289 "TJS", 290 "TMM", 291 "TMT", 292 "TND", 293 "TOP", 294 "TPE", 295 "TRL", 296 "TRY", 297 "TTD", 298 "TWD", 299 "TZS", 300 "UAH", 301 "UAK", 302 "UGX", 303 "USD", 304 "USN", 305 "USS", 306 "UYI", 307 "UYU", 308 "UZS", 309 "VEB", 310 "VEF", 311 "VND", 312 "VUV", 313 "WST", 314 "XAF", 315 "XAG", 316 "XAU", 317 "XBA", 318 "XBB", 319 "XBC", 320 "XBD", 321 "XCD", 322 "XDR", 323 "XEU", 324 "XOF", 325 "XPD", 326 "XPF", 327 "XPT", 328 "XSU", 329 "XTS", 330 "XUA", 331 "XXX", 332 "YDD", 333 "YER", 334 "YUM", 335 "YUN", 336 "ZAL", 337 "ZAR", 338 "ZMK", 339 "ZMW", 340 "ZRN", 341 "ZRZ", 342 "ZWD", 343 "ZWL", 344 "ZWN", 345 "ZWR", 346 "day", 347 "hour", 348 "millisecond", 349 "minute", 350 "month", 351 "second", 352 "week", 353 "year", 354 "centimeter", 355 "foot", 356 "inch", 357 "kilometer", 358 "light-year", 359 "meter", 360 "mile", 361 "millimeter", 362 "picometer", 363 "yard", 364 "gram", 365 "kilogram", 366 "ounce", 367 "pound", 368 "horsepower", 369 "kilowatt", 370 "watt", 371 "hectopascal", 372 "inch-hg", 373 "millibar", 374 "kilometer-per-hour", 375 "meter-per-second", 376 "mile-per-hour", 377 "celsius", 378 "fahrenheit", 379 "cubic-kilometer", 380 "cubic-mile", 381 "liter" 382 }; 383 384 MeasureUnit *MeasureUnit::createGForce(UErrorCode &status) { 385 return MeasureUnit::create(0, 0, status); 386 } 387 388 MeasureUnit *MeasureUnit::createArcMinute(UErrorCode &status) { 389 return MeasureUnit::create(1, 0, status); 390 } 391 392 MeasureUnit *MeasureUnit::createArcSecond(UErrorCode &status) { 393 return MeasureUnit::create(1, 1, status); 394 } 395 396 MeasureUnit *MeasureUnit::createDegree(UErrorCode &status) { 397 return MeasureUnit::create(1, 2, status); 398 } 399 400 MeasureUnit *MeasureUnit::createAcre(UErrorCode &status) { 401 return MeasureUnit::create(2, 0, status); 402 } 403 404 MeasureUnit *MeasureUnit::createHectare(UErrorCode &status) { 405 return MeasureUnit::create(2, 1, status); 406 } 407 408 MeasureUnit *MeasureUnit::createSquareFoot(UErrorCode &status) { 409 return MeasureUnit::create(2, 2, status); 410 } 411 412 MeasureUnit *MeasureUnit::createSquareKilometer(UErrorCode &status) { 413 return MeasureUnit::create(2, 3, status); 414 } 415 416 MeasureUnit *MeasureUnit::createSquareMeter(UErrorCode &status) { 417 return MeasureUnit::create(2, 4, status); 418 } 419 420 MeasureUnit *MeasureUnit::createSquareMile(UErrorCode &status) { 421 return MeasureUnit::create(2, 5, status); 422 } 423 424 MeasureUnit *MeasureUnit::createDay(UErrorCode &status) { 425 return MeasureUnit::create(4, 0, status); 426 } 427 428 MeasureUnit *MeasureUnit::createHour(UErrorCode &status) { 429 return MeasureUnit::create(4, 1, status); 430 } 431 432 MeasureUnit *MeasureUnit::createMillisecond(UErrorCode &status) { 433 return MeasureUnit::create(4, 2, status); 434 } 435 436 MeasureUnit *MeasureUnit::createMinute(UErrorCode &status) { 437 return MeasureUnit::create(4, 3, status); 438 } 439 440 MeasureUnit *MeasureUnit::createMonth(UErrorCode &status) { 441 return MeasureUnit::create(4, 4, status); 442 } 443 444 MeasureUnit *MeasureUnit::createSecond(UErrorCode &status) { 445 return MeasureUnit::create(4, 5, status); 446 } 447 448 MeasureUnit *MeasureUnit::createWeek(UErrorCode &status) { 449 return MeasureUnit::create(4, 6, status); 450 } 451 452 MeasureUnit *MeasureUnit::createYear(UErrorCode &status) { 453 return MeasureUnit::create(4, 7, status); 454 } 455 456 MeasureUnit *MeasureUnit::createCentimeter(UErrorCode &status) { 457 return MeasureUnit::create(5, 0, status); 458 } 459 460 MeasureUnit *MeasureUnit::createFoot(UErrorCode &status) { 461 return MeasureUnit::create(5, 1, status); 462 } 463 464 MeasureUnit *MeasureUnit::createInch(UErrorCode &status) { 465 return MeasureUnit::create(5, 2, status); 466 } 467 468 MeasureUnit *MeasureUnit::createKilometer(UErrorCode &status) { 469 return MeasureUnit::create(5, 3, status); 470 } 471 472 MeasureUnit *MeasureUnit::createLightYear(UErrorCode &status) { 473 return MeasureUnit::create(5, 4, status); 474 } 475 476 MeasureUnit *MeasureUnit::createMeter(UErrorCode &status) { 477 return MeasureUnit::create(5, 5, status); 478 } 479 480 MeasureUnit *MeasureUnit::createMile(UErrorCode &status) { 481 return MeasureUnit::create(5, 6, status); 482 } 483 484 MeasureUnit *MeasureUnit::createMillimeter(UErrorCode &status) { 485 return MeasureUnit::create(5, 7, status); 486 } 487 488 MeasureUnit *MeasureUnit::createPicometer(UErrorCode &status) { 489 return MeasureUnit::create(5, 8, status); 490 } 491 492 MeasureUnit *MeasureUnit::createYard(UErrorCode &status) { 493 return MeasureUnit::create(5, 9, status); 494 } 495 496 MeasureUnit *MeasureUnit::createGram(UErrorCode &status) { 497 return MeasureUnit::create(6, 0, status); 498 } 499 500 MeasureUnit *MeasureUnit::createKilogram(UErrorCode &status) { 501 return MeasureUnit::create(6, 1, status); 502 } 503 504 MeasureUnit *MeasureUnit::createOunce(UErrorCode &status) { 505 return MeasureUnit::create(6, 2, status); 506 } 507 508 MeasureUnit *MeasureUnit::createPound(UErrorCode &status) { 509 return MeasureUnit::create(6, 3, status); 510 } 511 512 MeasureUnit *MeasureUnit::createHorsepower(UErrorCode &status) { 513 return MeasureUnit::create(7, 0, status); 514 } 515 516 MeasureUnit *MeasureUnit::createKilowatt(UErrorCode &status) { 517 return MeasureUnit::create(7, 1, status); 518 } 519 520 MeasureUnit *MeasureUnit::createWatt(UErrorCode &status) { 521 return MeasureUnit::create(7, 2, status); 522 } 523 524 MeasureUnit *MeasureUnit::createHectopascal(UErrorCode &status) { 525 return MeasureUnit::create(8, 0, status); 526 } 527 528 MeasureUnit *MeasureUnit::createInchHg(UErrorCode &status) { 529 return MeasureUnit::create(8, 1, status); 530 } 531 532 MeasureUnit *MeasureUnit::createMillibar(UErrorCode &status) { 533 return MeasureUnit::create(8, 2, status); 534 } 535 536 MeasureUnit *MeasureUnit::createKilometerPerHour(UErrorCode &status) { 537 return MeasureUnit::create(9, 0, status); 538 } 539 540 MeasureUnit *MeasureUnit::createMeterPerSecond(UErrorCode &status) { 541 return MeasureUnit::create(9, 1, status); 542 } 543 544 MeasureUnit *MeasureUnit::createMilePerHour(UErrorCode &status) { 545 return MeasureUnit::create(9, 2, status); 546 } 547 548 MeasureUnit *MeasureUnit::createCelsius(UErrorCode &status) { 549 return MeasureUnit::create(10, 0, status); 550 } 551 552 MeasureUnit *MeasureUnit::createFahrenheit(UErrorCode &status) { 553 return MeasureUnit::create(10, 1, status); 554 } 555 556 MeasureUnit *MeasureUnit::createCubicKilometer(UErrorCode &status) { 557 return MeasureUnit::create(11, 0, status); 558 } 559 560 MeasureUnit *MeasureUnit::createCubicMile(UErrorCode &status) { 561 return MeasureUnit::create(11, 1, status); 562 } 563 564 MeasureUnit *MeasureUnit::createLiter(UErrorCode &status) { 565 return MeasureUnit::create(11, 2, status); 566 } 567 568 static int32_t binarySearch( 569 const char * const * array, int32_t start, int32_t end, const char * key) { 570 while (start < end) { 571 int32_t mid = (start + end) / 2; 572 int32_t cmp = uprv_strcmp(array[mid], key); 573 if (cmp < 0) { 574 start = mid + 1; 575 continue; 576 } 577 if (cmp == 0) { 578 return mid; 579 } 580 end = mid; 581 } 582 return -1; 583 } 584 585 MeasureUnit::MeasureUnit(const MeasureUnit &other) 586 : fTypeId(other.fTypeId), fSubTypeId(other.fSubTypeId) { 587 uprv_strcpy(fCurrency, other.fCurrency); 588 } 589 590 MeasureUnit &MeasureUnit::operator=(const MeasureUnit &other) { 591 if (this == &other) { 592 return *this; 593 } 594 fTypeId = other.fTypeId; 595 fSubTypeId = other.fSubTypeId; 596 uprv_strcpy(fCurrency, other.fCurrency); 597 return *this; 598 } 599 600 UObject *MeasureUnit::clone() const { 601 return new MeasureUnit(*this); 602 } 603 604 MeasureUnit::~MeasureUnit() { 605 } 606 607 const char *MeasureUnit::getType() const { 608 return gTypes[fTypeId]; 609 } 610 611 const char *MeasureUnit::getSubtype() const { 612 return fCurrency[0] == 0 ? gSubTypes[getOffset()] : fCurrency; 613 } 614 615 UBool MeasureUnit::operator==(const UObject& other) const { 616 if (this == &other) { // Same object, equal 617 return TRUE; 618 } 619 if (typeid(*this) != typeid(other)) { // Different types, not equal 620 return FALSE; 621 } 622 const MeasureUnit &rhs = static_cast<const MeasureUnit&>(other); 623 return ( 624 fTypeId == rhs.fTypeId 625 && fSubTypeId == rhs.fSubTypeId 626 && uprv_strcmp(fCurrency, rhs.fCurrency) == 0); 627 } 628 629 int32_t MeasureUnit::getIndex() const { 630 return gIndexes[fTypeId] + fSubTypeId; 631 } 632 633 int32_t MeasureUnit::getAvailable( 634 MeasureUnit *dest, 635 int32_t destCapacity, 636 UErrorCode &errorCode) { 637 if (U_FAILURE(errorCode)) { 638 return 0; 639 } 640 if (destCapacity < LENGTHOF(gSubTypes)) { 641 errorCode = U_BUFFER_OVERFLOW_ERROR; 642 return LENGTHOF(gSubTypes); 643 } 644 int32_t idx = 0; 645 for (int32_t typeIdx = 0; typeIdx < LENGTHOF(gTypes); ++typeIdx) { 646 int32_t len = gOffsets[typeIdx + 1] - gOffsets[typeIdx]; 647 for (int32_t subTypeIdx = 0; subTypeIdx < len; ++subTypeIdx) { 648 dest[idx].setTo(typeIdx, subTypeIdx); 649 ++idx; 650 } 651 } 652 U_ASSERT(idx == LENGTHOF(gSubTypes)); 653 return LENGTHOF(gSubTypes); 654 } 655 656 int32_t MeasureUnit::getAvailable( 657 const char *type, 658 MeasureUnit *dest, 659 int32_t destCapacity, 660 UErrorCode &errorCode) { 661 if (U_FAILURE(errorCode)) { 662 return 0; 663 } 664 int32_t typeIdx = binarySearch(gTypes, 0, LENGTHOF(gTypes), type); 665 if (typeIdx == -1) { 666 return 0; 667 } 668 int32_t len = gOffsets[typeIdx + 1] - gOffsets[typeIdx]; 669 if (destCapacity < len) { 670 errorCode = U_BUFFER_OVERFLOW_ERROR; 671 return len; 672 } 673 for (int subTypeIdx = 0; subTypeIdx < len; ++subTypeIdx) { 674 dest[subTypeIdx].setTo(typeIdx, subTypeIdx); 675 } 676 return len; 677 } 678 679 StringEnumeration* MeasureUnit::getAvailableTypes(UErrorCode &errorCode) { 680 UEnumeration *uenum = uenum_openCharStringsEnumeration( 681 gTypes, LENGTHOF(gTypes), &errorCode); 682 if (U_FAILURE(errorCode)) { 683 uenum_close(uenum); 684 return NULL; 685 } 686 StringEnumeration *result = new UStringEnumeration(uenum); 687 if (result == NULL) { 688 errorCode = U_MEMORY_ALLOCATION_ERROR; 689 uenum_close(uenum); 690 return NULL; 691 } 692 return result; 693 } 694 695 int32_t MeasureUnit::getIndexCount() { 696 return gIndexes[LENGTHOF(gIndexes) - 1]; 697 } 698 699 MeasureUnit *MeasureUnit::create(int typeId, int subTypeId, UErrorCode &status) { 700 if (U_FAILURE(status)) { 701 return NULL; 702 } 703 MeasureUnit *result = new MeasureUnit(typeId, subTypeId); 704 if (result == NULL) { 705 status = U_MEMORY_ALLOCATION_ERROR; 706 } 707 return result; 708 } 709 710 void MeasureUnit::initTime(const char *timeId) { 711 int32_t result = binarySearch(gTypes, 0, LENGTHOF(gTypes), "duration"); 712 U_ASSERT(result != -1); 713 fTypeId = result; 714 result = binarySearch(gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], timeId); 715 U_ASSERT(result != -1); 716 fSubTypeId = result - gOffsets[fTypeId]; 717 } 718 719 void MeasureUnit::initCurrency(const char *isoCurrency) { 720 int32_t result = binarySearch(gTypes, 0, LENGTHOF(gTypes), "currency"); 721 U_ASSERT(result != -1); 722 fTypeId = result; 723 result = binarySearch( 724 gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], isoCurrency); 725 if (result != -1) { 726 fSubTypeId = result - gOffsets[fTypeId]; 727 } else { 728 uprv_strncpy(fCurrency, isoCurrency, LENGTHOF(fCurrency)); 729 } 730 } 731 732 void MeasureUnit::setTo(int32_t typeId, int32_t subTypeId) { 733 fTypeId = typeId; 734 fSubTypeId = subTypeId; 735 fCurrency[0] = 0; 736 } 737 738 int32_t MeasureUnit::getOffset() const { 739 return gOffsets[fTypeId] + fSubTypeId; 740 } 741 742 U_NAMESPACE_END 743 744 #endif /* !UNCONFIG_NO_FORMATTING */ 745