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