]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/measunit.cpp
ICU-531.31.tar.gz
[apple/icu.git] / icuSources / i18n / measunit.cpp
CommitLineData
57a6839d
A
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 */