Home | History | Annotate | Download | only in i18n
      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