]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/measunit.cpp
ICU-531.48.tar.gz
[apple/icu.git] / icuSources / i18n / measunit.cpp
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 293, // Apple adjustments from here
37 296,
38 299,
39 302,
40 304,
41 307,
42 312 // Apple addition
43 };
44
45 static 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
62 static 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
78 static 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
393 MeasureUnit *MeasureUnit::createGForce(UErrorCode &status) {
394 return MeasureUnit::create(0, 0, status);
395 }
396
397 MeasureUnit *MeasureUnit::createArcMinute(UErrorCode &status) {
398 return MeasureUnit::create(1, 0, status);
399 }
400
401 MeasureUnit *MeasureUnit::createArcSecond(UErrorCode &status) {
402 return MeasureUnit::create(1, 1, status);
403 }
404
405 MeasureUnit *MeasureUnit::createDegree(UErrorCode &status) {
406 return MeasureUnit::create(1, 2, status);
407 }
408
409 MeasureUnit *MeasureUnit::createAcre(UErrorCode &status) {
410 return MeasureUnit::create(2, 0, status);
411 }
412
413 MeasureUnit *MeasureUnit::createHectare(UErrorCode &status) {
414 return MeasureUnit::create(2, 1, status);
415 }
416
417 MeasureUnit *MeasureUnit::createSquareFoot(UErrorCode &status) {
418 return MeasureUnit::create(2, 2, status);
419 }
420
421 MeasureUnit *MeasureUnit::createSquareKilometer(UErrorCode &status) {
422 return MeasureUnit::create(2, 3, status);
423 }
424
425 MeasureUnit *MeasureUnit::createSquareMeter(UErrorCode &status) {
426 return MeasureUnit::create(2, 4, status);
427 }
428
429 MeasureUnit *MeasureUnit::createSquareMile(UErrorCode &status) {
430 return MeasureUnit::create(2, 5, status);
431 }
432
433 MeasureUnit *MeasureUnit::createDay(UErrorCode &status) {
434 return MeasureUnit::create(4, 0, status);
435 }
436
437 MeasureUnit *MeasureUnit::createHour(UErrorCode &status) {
438 return MeasureUnit::create(4, 1, status);
439 }
440
441 MeasureUnit *MeasureUnit::createMillisecond(UErrorCode &status) {
442 return MeasureUnit::create(4, 2, status);
443 }
444
445 MeasureUnit *MeasureUnit::createMinute(UErrorCode &status) {
446 return MeasureUnit::create(4, 3, status);
447 }
448
449 MeasureUnit *MeasureUnit::createMonth(UErrorCode &status) {
450 return MeasureUnit::create(4, 4, status);
451 }
452
453 MeasureUnit *MeasureUnit::createSecond(UErrorCode &status) {
454 return MeasureUnit::create(4, 5, status);
455 }
456
457 MeasureUnit *MeasureUnit::createWeek(UErrorCode &status) {
458 return MeasureUnit::create(4, 6, status);
459 }
460
461 MeasureUnit *MeasureUnit::createYear(UErrorCode &status) {
462 return MeasureUnit::create(4, 7, status);
463 }
464
465 MeasureUnit *MeasureUnit::createCentimeter(UErrorCode &status) {
466 return MeasureUnit::create(5, 0, status);
467 }
468
469 MeasureUnit *MeasureUnit::createFoot(UErrorCode &status) {
470 return MeasureUnit::create(5, 1, status);
471 }
472
473 MeasureUnit *MeasureUnit::createInch(UErrorCode &status) {
474 return MeasureUnit::create(5, 2, status);
475 }
476
477 MeasureUnit *MeasureUnit::createKilometer(UErrorCode &status) {
478 return MeasureUnit::create(5, 3, status);
479 }
480
481 MeasureUnit *MeasureUnit::createLightYear(UErrorCode &status) {
482 return MeasureUnit::create(5, 4, status);
483 }
484
485 MeasureUnit *MeasureUnit::createMeter(UErrorCode &status) {
486 return MeasureUnit::create(5, 5, status);
487 }
488
489 MeasureUnit *MeasureUnit::createMile(UErrorCode &status) {
490 return MeasureUnit::create(5, 6, status);
491 }
492
493 MeasureUnit *MeasureUnit::createMillimeter(UErrorCode &status) {
494 return MeasureUnit::create(5, 7, status);
495 }
496
497 MeasureUnit *MeasureUnit::createPicometer(UErrorCode &status) {
498 return MeasureUnit::create(5, 8, status);
499 }
500
501 MeasureUnit *MeasureUnit::createYard(UErrorCode &status) {
502 return MeasureUnit::create(5, 9, status);
503 }
504
505 MeasureUnit *MeasureUnit::createGram(UErrorCode &status) {
506 return MeasureUnit::create(6, 0, status);
507 }
508
509 MeasureUnit *MeasureUnit::createKilogram(UErrorCode &status) {
510 return MeasureUnit::create(6, 1, status);
511 }
512
513 MeasureUnit *MeasureUnit::createOunce(UErrorCode &status) {
514 return MeasureUnit::create(6, 2, status);
515 }
516
517 MeasureUnit *MeasureUnit::createPound(UErrorCode &status) {
518 return MeasureUnit::create(6, 3, status);
519 }
520
521 MeasureUnit *MeasureUnit::createStone(UErrorCode &status) {
522 return MeasureUnit::create(6, 4, status);
523 }
524
525 MeasureUnit *MeasureUnit::createHorsepower(UErrorCode &status) {
526 return MeasureUnit::create(7, 0, status);
527 }
528
529 MeasureUnit *MeasureUnit::createKilowatt(UErrorCode &status) {
530 return MeasureUnit::create(7, 1, status);
531 }
532
533 MeasureUnit *MeasureUnit::createWatt(UErrorCode &status) {
534 return MeasureUnit::create(7, 2, status);
535 }
536
537 MeasureUnit *MeasureUnit::createHectopascal(UErrorCode &status) {
538 return MeasureUnit::create(8, 0, status);
539 }
540
541 MeasureUnit *MeasureUnit::createInchHg(UErrorCode &status) {
542 return MeasureUnit::create(8, 1, status);
543 }
544
545 MeasureUnit *MeasureUnit::createMillibar(UErrorCode &status) {
546 return MeasureUnit::create(8, 2, status);
547 }
548
549 MeasureUnit *MeasureUnit::createKilometerPerHour(UErrorCode &status) {
550 return MeasureUnit::create(9, 0, status);
551 }
552
553 MeasureUnit *MeasureUnit::createMeterPerSecond(UErrorCode &status) {
554 return MeasureUnit::create(9, 1, status);
555 }
556
557 MeasureUnit *MeasureUnit::createMilePerHour(UErrorCode &status) {
558 return MeasureUnit::create(9, 2, status);
559 }
560
561 MeasureUnit *MeasureUnit::createCelsius(UErrorCode &status) {
562 return MeasureUnit::create(10, 0, status);
563 }
564
565 MeasureUnit *MeasureUnit::createFahrenheit(UErrorCode &status) {
566 return MeasureUnit::create(10, 1, status);
567 }
568
569 MeasureUnit *MeasureUnit::createCubicKilometer(UErrorCode &status) {
570 return MeasureUnit::create(11, 0, status);
571 }
572
573 MeasureUnit *MeasureUnit::createCubicMile(UErrorCode &status) {
574 return MeasureUnit::create(11, 1, status);
575 }
576
577 MeasureUnit *MeasureUnit::createLiter(UErrorCode &status) {
578 return MeasureUnit::create(11, 2, status);
579 }
580
581 MeasureUnit *MeasureUnit::createCalorie(UErrorCode &status) {
582 return MeasureUnit::create(12, 0, status);
583 }
584
585 MeasureUnit *MeasureUnit::createFoodcalorie(UErrorCode &status) {
586 return MeasureUnit::create(12, 1, status);
587 }
588
589 MeasureUnit *MeasureUnit::createJoule(UErrorCode &status) {
590 return MeasureUnit::create(12, 2, status);
591 }
592
593 MeasureUnit *MeasureUnit::createKilocalorie(UErrorCode &status) {
594 return MeasureUnit::create(12, 3, status);
595 }
596
597 MeasureUnit *MeasureUnit::createKilojoule(UErrorCode &status) {
598 return MeasureUnit::create(12, 4, status);
599 }
600
601
602 static 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
619 MeasureUnit::MeasureUnit(const MeasureUnit &other)
620 : fTypeId(other.fTypeId), fSubTypeId(other.fSubTypeId) {
621 uprv_strcpy(fCurrency, other.fCurrency);
622 }
623
624 MeasureUnit &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
634 UObject *MeasureUnit::clone() const {
635 return new MeasureUnit(*this);
636 }
637
638 MeasureUnit::~MeasureUnit() {
639 }
640
641 const char *MeasureUnit::getType() const {
642 return gTypes[fTypeId];
643 }
644
645 const char *MeasureUnit::getSubtype() const {
646 return fCurrency[0] == 0 ? gSubTypes[getOffset()] : fCurrency;
647 }
648
649 UBool 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
663 int32_t MeasureUnit::getIndex() const {
664 return gIndexes[fTypeId] + fSubTypeId;
665 }
666
667 int32_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
690 int32_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
717 StringEnumeration* 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
733 int32_t MeasureUnit::getIndexCount() {
734 return gIndexes[LENGTHOF(gIndexes) - 1];
735 }
736
737 MeasureUnit *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
748 void 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
757 void 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
770 void MeasureUnit::setTo(int32_t typeId, int32_t subTypeId) {
771 fTypeId = typeId;
772 fSubTypeId = subTypeId;
773 fCurrency[0] = 0;
774 }
775
776 int32_t MeasureUnit::getOffset() const {
777 return gOffsets[fTypeId] + fSubTypeId;
778 }
779
780 U_NAMESPACE_END
781
782 #endif /* !UNCONFIG_NO_FORMATTING */