0a42d4959f
X-SVN-Rev: 35069
735 lines
14 KiB
C++
735 lines
14 KiB
C++
/*
|
|
**********************************************************************
|
|
* Copyright (c) 2004-2014, International Business Machines
|
|
* Corporation and others. All Rights Reserved.
|
|
**********************************************************************
|
|
* Author: Alan Liu
|
|
* Created: April 26, 2004
|
|
* Since: ICU 3.0
|
|
**********************************************************************
|
|
*/
|
|
#include "unicode/measunit.h"
|
|
#include "unicode/uenum.h"
|
|
#include "ustrenum.h"
|
|
#include "cstring.h"
|
|
#include "uassert.h"
|
|
|
|
#define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0]))
|
|
|
|
U_NAMESPACE_BEGIN
|
|
|
|
static const int32_t gOffsets[] = {
|
|
0,
|
|
1,
|
|
4,
|
|
10,
|
|
270,
|
|
278,
|
|
288,
|
|
292,
|
|
295,
|
|
298,
|
|
301,
|
|
303,
|
|
306
|
|
};
|
|
|
|
static const int32_t gIndexes[] = {
|
|
0,
|
|
1,
|
|
4,
|
|
10,
|
|
10,
|
|
18,
|
|
28,
|
|
32,
|
|
35,
|
|
38,
|
|
41,
|
|
43,
|
|
46
|
|
};
|
|
|
|
static const char * const gTypes[] = {
|
|
"acceleration",
|
|
"angle",
|
|
"area",
|
|
"currency",
|
|
"duration",
|
|
"length",
|
|
"mass",
|
|
"power",
|
|
"pressure",
|
|
"speed",
|
|
"temperature",
|
|
"volume"
|
|
};
|
|
|
|
static const char * const gSubTypes[] = {
|
|
"g-force",
|
|
"arc-minute",
|
|
"arc-second",
|
|
"degree",
|
|
"acre",
|
|
"hectare",
|
|
"square-foot",
|
|
"square-kilometer",
|
|
"square-meter",
|
|
"square-mile",
|
|
"ADP",
|
|
"AED",
|
|
"AFA",
|
|
"AFN",
|
|
"ALL",
|
|
"AMD",
|
|
"ANG",
|
|
"AOA",
|
|
"AON",
|
|
"AOR",
|
|
"ARA",
|
|
"ARP",
|
|
"ARS",
|
|
"ATS",
|
|
"AUD",
|
|
"AWG",
|
|
"AYM",
|
|
"AZM",
|
|
"AZN",
|
|
"BAD",
|
|
"BAM",
|
|
"BBD",
|
|
"BDT",
|
|
"BEC",
|
|
"BEF",
|
|
"BEL",
|
|
"BGL",
|
|
"BGN",
|
|
"BHD",
|
|
"BIF",
|
|
"BMD",
|
|
"BND",
|
|
"BOB",
|
|
"BOV",
|
|
"BRC",
|
|
"BRE",
|
|
"BRL",
|
|
"BRN",
|
|
"BRR",
|
|
"BSD",
|
|
"BTN",
|
|
"BWP",
|
|
"BYB",
|
|
"BYR",
|
|
"BZD",
|
|
"CAD",
|
|
"CDF",
|
|
"CHC",
|
|
"CHE",
|
|
"CHF",
|
|
"CHW",
|
|
"CLF",
|
|
"CLP",
|
|
"CNY",
|
|
"COP",
|
|
"COU",
|
|
"CRC",
|
|
"CSD",
|
|
"CSK",
|
|
"CUC",
|
|
"CUP",
|
|
"CVE",
|
|
"CYP",
|
|
"CZK",
|
|
"DDM",
|
|
"DEM",
|
|
"DJF",
|
|
"DKK",
|
|
"DOP",
|
|
"DZD",
|
|
"ECS",
|
|
"ECV",
|
|
"EEK",
|
|
"EGP",
|
|
"ERN",
|
|
"ESA",
|
|
"ESB",
|
|
"ESP",
|
|
"ETB",
|
|
"EUR",
|
|
"FIM",
|
|
"FJD",
|
|
"FKP",
|
|
"FRF",
|
|
"GBP",
|
|
"GEK",
|
|
"GEL",
|
|
"GHC",
|
|
"GHP",
|
|
"GHS",
|
|
"GIP",
|
|
"GMD",
|
|
"GNF",
|
|
"GQE",
|
|
"GRD",
|
|
"GTQ",
|
|
"GWP",
|
|
"GYD",
|
|
"HKD",
|
|
"HNL",
|
|
"HRD",
|
|
"HRK",
|
|
"HTG",
|
|
"HUF",
|
|
"IDR",
|
|
"IEP",
|
|
"ILS",
|
|
"INR",
|
|
"IQD",
|
|
"IRR",
|
|
"ISK",
|
|
"ITL",
|
|
"JMD",
|
|
"JOD",
|
|
"JPY",
|
|
"KES",
|
|
"KGS",
|
|
"KHR",
|
|
"KMF",
|
|
"KPW",
|
|
"KRW",
|
|
"KWD",
|
|
"KYD",
|
|
"KZT",
|
|
"LAK",
|
|
"LBP",
|
|
"LKR",
|
|
"LRD",
|
|
"LSL",
|
|
"LTL",
|
|
"LTT",
|
|
"LUC",
|
|
"LUF",
|
|
"LUL",
|
|
"LVL",
|
|
"LVR",
|
|
"LYD",
|
|
"MAD",
|
|
"MDL",
|
|
"MGA",
|
|
"MGF",
|
|
"MKD",
|
|
"MLF",
|
|
"MMK",
|
|
"MNT",
|
|
"MOP",
|
|
"MRO",
|
|
"MTL",
|
|
"MUR",
|
|
"MVR",
|
|
"MWK",
|
|
"MXN",
|
|
"MXV",
|
|
"MYR",
|
|
"MZM",
|
|
"MZN",
|
|
"NAD",
|
|
"NGN",
|
|
"NIO",
|
|
"NLG",
|
|
"NOK",
|
|
"NPR",
|
|
"NZD",
|
|
"OMR",
|
|
"PAB",
|
|
"PEI",
|
|
"PEN",
|
|
"PES",
|
|
"PGK",
|
|
"PHP",
|
|
"PKR",
|
|
"PLN",
|
|
"PLZ",
|
|
"PTE",
|
|
"PYG",
|
|
"QAR",
|
|
"ROL",
|
|
"RON",
|
|
"RSD",
|
|
"RUB",
|
|
"RUR",
|
|
"RWF",
|
|
"SAR",
|
|
"SBD",
|
|
"SCR",
|
|
"SDD",
|
|
"SDG",
|
|
"SEK",
|
|
"SGD",
|
|
"SHP",
|
|
"SIT",
|
|
"SKK",
|
|
"SLL",
|
|
"SOS",
|
|
"SRD",
|
|
"SRG",
|
|
"SSP",
|
|
"STD",
|
|
"SVC",
|
|
"SYP",
|
|
"SZL",
|
|
"THB",
|
|
"TJR",
|
|
"TJS",
|
|
"TMM",
|
|
"TMT",
|
|
"TND",
|
|
"TOP",
|
|
"TPE",
|
|
"TRL",
|
|
"TRY",
|
|
"TTD",
|
|
"TWD",
|
|
"TZS",
|
|
"UAH",
|
|
"UAK",
|
|
"UGX",
|
|
"USD",
|
|
"USN",
|
|
"USS",
|
|
"UYI",
|
|
"UYU",
|
|
"UZS",
|
|
"VEB",
|
|
"VEF",
|
|
"VND",
|
|
"VUV",
|
|
"WST",
|
|
"XAF",
|
|
"XAG",
|
|
"XAU",
|
|
"XBA",
|
|
"XBB",
|
|
"XBC",
|
|
"XBD",
|
|
"XCD",
|
|
"XDR",
|
|
"XEU",
|
|
"XOF",
|
|
"XPD",
|
|
"XPF",
|
|
"XPT",
|
|
"XSU",
|
|
"XTS",
|
|
"XUA",
|
|
"XXX",
|
|
"YDD",
|
|
"YER",
|
|
"YUM",
|
|
"YUN",
|
|
"ZAL",
|
|
"ZAR",
|
|
"ZMK",
|
|
"ZMW",
|
|
"ZRN",
|
|
"ZRZ",
|
|
"ZWD",
|
|
"ZWL",
|
|
"ZWN",
|
|
"ZWR",
|
|
"day",
|
|
"hour",
|
|
"millisecond",
|
|
"minute",
|
|
"month",
|
|
"second",
|
|
"week",
|
|
"year",
|
|
"centimeter",
|
|
"foot",
|
|
"inch",
|
|
"kilometer",
|
|
"light-year",
|
|
"meter",
|
|
"mile",
|
|
"millimeter",
|
|
"picometer",
|
|
"yard",
|
|
"gram",
|
|
"kilogram",
|
|
"ounce",
|
|
"pound",
|
|
"horsepower",
|
|
"kilowatt",
|
|
"watt",
|
|
"hectopascal",
|
|
"inch-hg",
|
|
"millibar",
|
|
"kilometer-per-hour",
|
|
"meter-per-second",
|
|
"mile-per-hour",
|
|
"celsius",
|
|
"fahrenheit",
|
|
"cubic-kilometer",
|
|
"cubic-mile",
|
|
"liter"
|
|
};
|
|
|
|
MeasureUnit *MeasureUnit::createGForce(UErrorCode &status) {
|
|
return MeasureUnit::create(0, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createArcMinute(UErrorCode &status) {
|
|
return MeasureUnit::create(1, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createArcSecond(UErrorCode &status) {
|
|
return MeasureUnit::create(1, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createDegree(UErrorCode &status) {
|
|
return MeasureUnit::create(1, 2, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createAcre(UErrorCode &status) {
|
|
return MeasureUnit::create(2, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createHectare(UErrorCode &status) {
|
|
return MeasureUnit::create(2, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createSquareFoot(UErrorCode &status) {
|
|
return MeasureUnit::create(2, 2, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createSquareKilometer(UErrorCode &status) {
|
|
return MeasureUnit::create(2, 3, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createSquareMeter(UErrorCode &status) {
|
|
return MeasureUnit::create(2, 4, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createSquareMile(UErrorCode &status) {
|
|
return MeasureUnit::create(2, 5, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createDay(UErrorCode &status) {
|
|
return MeasureUnit::create(4, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createHour(UErrorCode &status) {
|
|
return MeasureUnit::create(4, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMillisecond(UErrorCode &status) {
|
|
return MeasureUnit::create(4, 2, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMinute(UErrorCode &status) {
|
|
return MeasureUnit::create(4, 3, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMonth(UErrorCode &status) {
|
|
return MeasureUnit::create(4, 4, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createSecond(UErrorCode &status) {
|
|
return MeasureUnit::create(4, 5, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createWeek(UErrorCode &status) {
|
|
return MeasureUnit::create(4, 6, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createYear(UErrorCode &status) {
|
|
return MeasureUnit::create(4, 7, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createCentimeter(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createFoot(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createInch(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 2, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createKilometer(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 3, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createLightYear(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 4, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMeter(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 5, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMile(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 6, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMillimeter(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 7, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createPicometer(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 8, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createYard(UErrorCode &status) {
|
|
return MeasureUnit::create(5, 9, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createGram(UErrorCode &status) {
|
|
return MeasureUnit::create(6, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createKilogram(UErrorCode &status) {
|
|
return MeasureUnit::create(6, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createOunce(UErrorCode &status) {
|
|
return MeasureUnit::create(6, 2, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createPound(UErrorCode &status) {
|
|
return MeasureUnit::create(6, 3, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createHorsepower(UErrorCode &status) {
|
|
return MeasureUnit::create(7, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createKilowatt(UErrorCode &status) {
|
|
return MeasureUnit::create(7, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createWatt(UErrorCode &status) {
|
|
return MeasureUnit::create(7, 2, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createHectopascal(UErrorCode &status) {
|
|
return MeasureUnit::create(8, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createInchHg(UErrorCode &status) {
|
|
return MeasureUnit::create(8, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMillibar(UErrorCode &status) {
|
|
return MeasureUnit::create(8, 2, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createKilometerPerHour(UErrorCode &status) {
|
|
return MeasureUnit::create(9, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMeterPerSecond(UErrorCode &status) {
|
|
return MeasureUnit::create(9, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createMilePerHour(UErrorCode &status) {
|
|
return MeasureUnit::create(9, 2, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createCelsius(UErrorCode &status) {
|
|
return MeasureUnit::create(10, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createFahrenheit(UErrorCode &status) {
|
|
return MeasureUnit::create(10, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createCubicKilometer(UErrorCode &status) {
|
|
return MeasureUnit::create(11, 0, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createCubicMile(UErrorCode &status) {
|
|
return MeasureUnit::create(11, 1, status);
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::createLiter(UErrorCode &status) {
|
|
return MeasureUnit::create(11, 2, status);
|
|
}
|
|
|
|
static int32_t binarySearch(
|
|
const char * const * array, int32_t start, int32_t end, const char * key) {
|
|
while (start < end) {
|
|
int32_t mid = (start + end) / 2;
|
|
int32_t cmp = uprv_strcmp(array[mid], key);
|
|
if (cmp < 0) {
|
|
start = mid + 1;
|
|
continue;
|
|
}
|
|
if (cmp == 0) {
|
|
return mid;
|
|
}
|
|
end = mid;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
MeasureUnit::MeasureUnit(const MeasureUnit &other)
|
|
: fTypeId(other.fTypeId), fSubTypeId(other.fSubTypeId) {
|
|
uprv_strcpy(fCurrency, other.fCurrency);
|
|
}
|
|
|
|
MeasureUnit &MeasureUnit::operator=(const MeasureUnit &other) {
|
|
if (this == &other) {
|
|
return *this;
|
|
}
|
|
fTypeId = other.fTypeId;
|
|
fSubTypeId = other.fSubTypeId;
|
|
uprv_strcpy(fCurrency, other.fCurrency);
|
|
return *this;
|
|
}
|
|
|
|
UObject *MeasureUnit::clone() const {
|
|
return new MeasureUnit(*this);
|
|
}
|
|
|
|
MeasureUnit::~MeasureUnit() {
|
|
}
|
|
|
|
const char *MeasureUnit::getType() const {
|
|
return gTypes[fTypeId];
|
|
}
|
|
|
|
const char *MeasureUnit::getSubtype() const {
|
|
return fCurrency[0] == 0 ? gSubTypes[getOffset()] : fCurrency;
|
|
}
|
|
|
|
UBool MeasureUnit::operator==(const UObject& other) const {
|
|
const MeasureUnit *rhs = dynamic_cast<const MeasureUnit*>(&other);
|
|
if (rhs == NULL) {
|
|
return FALSE;
|
|
}
|
|
return (
|
|
fTypeId == rhs->fTypeId
|
|
&& fSubTypeId == rhs->fSubTypeId
|
|
&& uprv_strcmp(fCurrency, rhs->fCurrency) == 0);
|
|
}
|
|
|
|
int32_t MeasureUnit::getIndex() const {
|
|
return gIndexes[fTypeId] + fSubTypeId;
|
|
}
|
|
|
|
int32_t MeasureUnit::getAvailable(
|
|
MeasureUnit *dest,
|
|
int32_t destCapacity,
|
|
UErrorCode &errorCode) {
|
|
if (U_FAILURE(errorCode)) {
|
|
return 0;
|
|
}
|
|
if (destCapacity < LENGTHOF(gSubTypes)) {
|
|
errorCode = U_BUFFER_OVERFLOW_ERROR;
|
|
return LENGTHOF(gSubTypes);
|
|
}
|
|
int32_t idx = 0;
|
|
for (int32_t typeIdx = 0; typeIdx < LENGTHOF(gTypes); ++typeIdx) {
|
|
int32_t len = gOffsets[typeIdx + 1] - gOffsets[typeIdx];
|
|
for (int32_t subTypeIdx = 0; subTypeIdx < len; ++subTypeIdx) {
|
|
dest[idx].setTo(typeIdx, subTypeIdx);
|
|
++idx;
|
|
}
|
|
}
|
|
U_ASSERT(idx == LENGTHOF(gSubTypes));
|
|
return LENGTHOF(gSubTypes);
|
|
}
|
|
|
|
int32_t MeasureUnit::getAvailable(
|
|
const char *type,
|
|
MeasureUnit *dest,
|
|
int32_t destCapacity,
|
|
UErrorCode &errorCode) {
|
|
if (U_FAILURE(errorCode)) {
|
|
return 0;
|
|
}
|
|
int32_t typeIdx = binarySearch(gTypes, 0, LENGTHOF(gTypes), type);
|
|
if (typeIdx == -1) {
|
|
return 0;
|
|
}
|
|
int32_t len = gOffsets[typeIdx + 1] - gOffsets[typeIdx];
|
|
if (destCapacity < len) {
|
|
errorCode = U_BUFFER_OVERFLOW_ERROR;
|
|
return len;
|
|
}
|
|
for (int subTypeIdx = 0; subTypeIdx < len; ++subTypeIdx) {
|
|
dest[subTypeIdx].setTo(typeIdx, subTypeIdx);
|
|
}
|
|
return len;
|
|
}
|
|
|
|
StringEnumeration* MeasureUnit::getAvailableTypes(UErrorCode &errorCode) {
|
|
UEnumeration *uenum = uenum_openCharStringsEnumeration(
|
|
gTypes, LENGTHOF(gTypes), &errorCode);
|
|
if (U_FAILURE(errorCode)) {
|
|
uenum_close(uenum);
|
|
return NULL;
|
|
}
|
|
StringEnumeration *result = new UStringEnumeration(uenum);
|
|
if (result == NULL) {
|
|
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
|
uenum_close(uenum);
|
|
return NULL;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int32_t MeasureUnit::getIndexCount() {
|
|
return gIndexes[LENGTHOF(gIndexes) - 1];
|
|
}
|
|
|
|
MeasureUnit *MeasureUnit::create(int typeId, int subTypeId, UErrorCode &status) {
|
|
if (U_FAILURE(status)) {
|
|
return NULL;
|
|
}
|
|
MeasureUnit *result = new MeasureUnit(typeId, subTypeId);
|
|
if (result == NULL) {
|
|
status = U_MEMORY_ALLOCATION_ERROR;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void MeasureUnit::initTime(const char *timeId) {
|
|
int32_t result = binarySearch(gTypes, 0, LENGTHOF(gTypes), "duration");
|
|
U_ASSERT(result != -1);
|
|
fTypeId = result;
|
|
result = binarySearch(gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], timeId);
|
|
U_ASSERT(result != -1);
|
|
fSubTypeId = result - gOffsets[fTypeId];
|
|
}
|
|
|
|
void MeasureUnit::initCurrency(const char *isoCurrency) {
|
|
int32_t result = binarySearch(gTypes, 0, LENGTHOF(gTypes), "currency");
|
|
U_ASSERT(result != -1);
|
|
fTypeId = result;
|
|
result = binarySearch(
|
|
gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], isoCurrency);
|
|
if (result != -1) {
|
|
fSubTypeId = result - gOffsets[fTypeId];
|
|
} else {
|
|
uprv_strncpy(fCurrency, isoCurrency, LENGTHOF(fCurrency));
|
|
}
|
|
}
|
|
|
|
void MeasureUnit::setTo(int32_t typeId, int32_t subTypeId) {
|
|
fTypeId = typeId;
|
|
fSubTypeId = subTypeId;
|
|
fCurrency[0] = 0;
|
|
}
|
|
|
|
int32_t MeasureUnit::getOffset() const {
|
|
return gOffsets[fTypeId] + fSubTypeId;
|
|
}
|
|
|
|
U_NAMESPACE_END
|
|
|
|
|