• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
createGForce(UErrorCode & status)384 MeasureUnit *MeasureUnit::createGForce(UErrorCode &status) {
385     return MeasureUnit::create(0, 0, status);
386 }
387 
createArcMinute(UErrorCode & status)388 MeasureUnit *MeasureUnit::createArcMinute(UErrorCode &status) {
389     return MeasureUnit::create(1, 0, status);
390 }
391 
createArcSecond(UErrorCode & status)392 MeasureUnit *MeasureUnit::createArcSecond(UErrorCode &status) {
393     return MeasureUnit::create(1, 1, status);
394 }
395 
createDegree(UErrorCode & status)396 MeasureUnit *MeasureUnit::createDegree(UErrorCode &status) {
397     return MeasureUnit::create(1, 2, status);
398 }
399 
createAcre(UErrorCode & status)400 MeasureUnit *MeasureUnit::createAcre(UErrorCode &status) {
401     return MeasureUnit::create(2, 0, status);
402 }
403 
createHectare(UErrorCode & status)404 MeasureUnit *MeasureUnit::createHectare(UErrorCode &status) {
405     return MeasureUnit::create(2, 1, status);
406 }
407 
createSquareFoot(UErrorCode & status)408 MeasureUnit *MeasureUnit::createSquareFoot(UErrorCode &status) {
409     return MeasureUnit::create(2, 2, status);
410 }
411 
createSquareKilometer(UErrorCode & status)412 MeasureUnit *MeasureUnit::createSquareKilometer(UErrorCode &status) {
413     return MeasureUnit::create(2, 3, status);
414 }
415 
createSquareMeter(UErrorCode & status)416 MeasureUnit *MeasureUnit::createSquareMeter(UErrorCode &status) {
417     return MeasureUnit::create(2, 4, status);
418 }
419 
createSquareMile(UErrorCode & status)420 MeasureUnit *MeasureUnit::createSquareMile(UErrorCode &status) {
421     return MeasureUnit::create(2, 5, status);
422 }
423 
createDay(UErrorCode & status)424 MeasureUnit *MeasureUnit::createDay(UErrorCode &status) {
425     return MeasureUnit::create(4, 0, status);
426 }
427 
createHour(UErrorCode & status)428 MeasureUnit *MeasureUnit::createHour(UErrorCode &status) {
429     return MeasureUnit::create(4, 1, status);
430 }
431 
createMillisecond(UErrorCode & status)432 MeasureUnit *MeasureUnit::createMillisecond(UErrorCode &status) {
433     return MeasureUnit::create(4, 2, status);
434 }
435 
createMinute(UErrorCode & status)436 MeasureUnit *MeasureUnit::createMinute(UErrorCode &status) {
437     return MeasureUnit::create(4, 3, status);
438 }
439 
createMonth(UErrorCode & status)440 MeasureUnit *MeasureUnit::createMonth(UErrorCode &status) {
441     return MeasureUnit::create(4, 4, status);
442 }
443 
createSecond(UErrorCode & status)444 MeasureUnit *MeasureUnit::createSecond(UErrorCode &status) {
445     return MeasureUnit::create(4, 5, status);
446 }
447 
createWeek(UErrorCode & status)448 MeasureUnit *MeasureUnit::createWeek(UErrorCode &status) {
449     return MeasureUnit::create(4, 6, status);
450 }
451 
createYear(UErrorCode & status)452 MeasureUnit *MeasureUnit::createYear(UErrorCode &status) {
453     return MeasureUnit::create(4, 7, status);
454 }
455 
createCentimeter(UErrorCode & status)456 MeasureUnit *MeasureUnit::createCentimeter(UErrorCode &status) {
457     return MeasureUnit::create(5, 0, status);
458 }
459 
createFoot(UErrorCode & status)460 MeasureUnit *MeasureUnit::createFoot(UErrorCode &status) {
461     return MeasureUnit::create(5, 1, status);
462 }
463 
createInch(UErrorCode & status)464 MeasureUnit *MeasureUnit::createInch(UErrorCode &status) {
465     return MeasureUnit::create(5, 2, status);
466 }
467 
createKilometer(UErrorCode & status)468 MeasureUnit *MeasureUnit::createKilometer(UErrorCode &status) {
469     return MeasureUnit::create(5, 3, status);
470 }
471 
createLightYear(UErrorCode & status)472 MeasureUnit *MeasureUnit::createLightYear(UErrorCode &status) {
473     return MeasureUnit::create(5, 4, status);
474 }
475 
createMeter(UErrorCode & status)476 MeasureUnit *MeasureUnit::createMeter(UErrorCode &status) {
477     return MeasureUnit::create(5, 5, status);
478 }
479 
createMile(UErrorCode & status)480 MeasureUnit *MeasureUnit::createMile(UErrorCode &status) {
481     return MeasureUnit::create(5, 6, status);
482 }
483 
createMillimeter(UErrorCode & status)484 MeasureUnit *MeasureUnit::createMillimeter(UErrorCode &status) {
485     return MeasureUnit::create(5, 7, status);
486 }
487 
createPicometer(UErrorCode & status)488 MeasureUnit *MeasureUnit::createPicometer(UErrorCode &status) {
489     return MeasureUnit::create(5, 8, status);
490 }
491 
createYard(UErrorCode & status)492 MeasureUnit *MeasureUnit::createYard(UErrorCode &status) {
493     return MeasureUnit::create(5, 9, status);
494 }
495 
createGram(UErrorCode & status)496 MeasureUnit *MeasureUnit::createGram(UErrorCode &status) {
497     return MeasureUnit::create(6, 0, status);
498 }
499 
createKilogram(UErrorCode & status)500 MeasureUnit *MeasureUnit::createKilogram(UErrorCode &status) {
501     return MeasureUnit::create(6, 1, status);
502 }
503 
createOunce(UErrorCode & status)504 MeasureUnit *MeasureUnit::createOunce(UErrorCode &status) {
505     return MeasureUnit::create(6, 2, status);
506 }
507 
createPound(UErrorCode & status)508 MeasureUnit *MeasureUnit::createPound(UErrorCode &status) {
509     return MeasureUnit::create(6, 3, status);
510 }
511 
createHorsepower(UErrorCode & status)512 MeasureUnit *MeasureUnit::createHorsepower(UErrorCode &status) {
513     return MeasureUnit::create(7, 0, status);
514 }
515 
createKilowatt(UErrorCode & status)516 MeasureUnit *MeasureUnit::createKilowatt(UErrorCode &status) {
517     return MeasureUnit::create(7, 1, status);
518 }
519 
createWatt(UErrorCode & status)520 MeasureUnit *MeasureUnit::createWatt(UErrorCode &status) {
521     return MeasureUnit::create(7, 2, status);
522 }
523 
createHectopascal(UErrorCode & status)524 MeasureUnit *MeasureUnit::createHectopascal(UErrorCode &status) {
525     return MeasureUnit::create(8, 0, status);
526 }
527 
createInchHg(UErrorCode & status)528 MeasureUnit *MeasureUnit::createInchHg(UErrorCode &status) {
529     return MeasureUnit::create(8, 1, status);
530 }
531 
createMillibar(UErrorCode & status)532 MeasureUnit *MeasureUnit::createMillibar(UErrorCode &status) {
533     return MeasureUnit::create(8, 2, status);
534 }
535 
createKilometerPerHour(UErrorCode & status)536 MeasureUnit *MeasureUnit::createKilometerPerHour(UErrorCode &status) {
537     return MeasureUnit::create(9, 0, status);
538 }
539 
createMeterPerSecond(UErrorCode & status)540 MeasureUnit *MeasureUnit::createMeterPerSecond(UErrorCode &status) {
541     return MeasureUnit::create(9, 1, status);
542 }
543 
createMilePerHour(UErrorCode & status)544 MeasureUnit *MeasureUnit::createMilePerHour(UErrorCode &status) {
545     return MeasureUnit::create(9, 2, status);
546 }
547 
createCelsius(UErrorCode & status)548 MeasureUnit *MeasureUnit::createCelsius(UErrorCode &status) {
549     return MeasureUnit::create(10, 0, status);
550 }
551 
createFahrenheit(UErrorCode & status)552 MeasureUnit *MeasureUnit::createFahrenheit(UErrorCode &status) {
553     return MeasureUnit::create(10, 1, status);
554 }
555 
createCubicKilometer(UErrorCode & status)556 MeasureUnit *MeasureUnit::createCubicKilometer(UErrorCode &status) {
557     return MeasureUnit::create(11, 0, status);
558 }
559 
createCubicMile(UErrorCode & status)560 MeasureUnit *MeasureUnit::createCubicMile(UErrorCode &status) {
561     return MeasureUnit::create(11, 1, status);
562 }
563 
createLiter(UErrorCode & status)564 MeasureUnit *MeasureUnit::createLiter(UErrorCode &status) {
565     return MeasureUnit::create(11, 2, status);
566 }
567 
binarySearch(const char * const * array,int32_t start,int32_t end,const char * key)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 
MeasureUnit(const MeasureUnit & other)585 MeasureUnit::MeasureUnit(const MeasureUnit &other)
586         : fTypeId(other.fTypeId), fSubTypeId(other.fSubTypeId) {
587     uprv_strcpy(fCurrency, other.fCurrency);
588 }
589 
operator =(const MeasureUnit & other)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 
clone() const600 UObject *MeasureUnit::clone() const {
601     return new MeasureUnit(*this);
602 }
603 
~MeasureUnit()604 MeasureUnit::~MeasureUnit() {
605 }
606 
getType() const607 const char *MeasureUnit::getType() const {
608     return gTypes[fTypeId];
609 }
610 
getSubtype() const611 const char *MeasureUnit::getSubtype() const {
612     return fCurrency[0] == 0 ? gSubTypes[getOffset()] : fCurrency;
613 }
614 
operator ==(const UObject & other) const615 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 
getIndex() const629 int32_t MeasureUnit::getIndex() const {
630     return gIndexes[fTypeId] + fSubTypeId;
631 }
632 
getAvailable(MeasureUnit * dest,int32_t destCapacity,UErrorCode & errorCode)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 
getAvailable(const char * type,MeasureUnit * dest,int32_t destCapacity,UErrorCode & errorCode)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 
getAvailableTypes(UErrorCode & errorCode)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 
getIndexCount()695 int32_t MeasureUnit::getIndexCount() {
696     return gIndexes[LENGTHOF(gIndexes) - 1];
697 }
698 
create(int typeId,int subTypeId,UErrorCode & status)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 
initTime(const char * timeId)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 
initCurrency(const char * isoCurrency)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 
setTo(int32_t typeId,int32_t subTypeId)732 void MeasureUnit::setTo(int32_t typeId, int32_t subTypeId) {
733     fTypeId = typeId;
734     fSubTypeId = subTypeId;
735     fCurrency[0] = 0;
736 }
737 
getOffset() const738 int32_t MeasureUnit::getOffset() const {
739     return gOffsets[fTypeId] + fSubTypeId;
740 }
741 
742 U_NAMESPACE_END
743 
744 #endif /* !UNCONFIG_NO_FORMATTING */
745