2 **********************************************************************
3 * Copyright (c) 2004-2014, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
7 * Created: April 26, 2004
9 **********************************************************************
11 #include "utypeinfo.h" // for 'typeid' to work
13 #include "unicode/measunit.h"
15 #if !UCONFIG_NO_FORMATTING
17 #include "unicode/uenum.h"
22 #define LENGTHOF(array) ((int32_t)(sizeof(array) / sizeof((array)[0])))
26 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureUnit
)
28 static const int32_t gOffsets
[] = {
36 293, // Apple adjustments from here
45 static const int32_t gIndexes
[] = {
53 33, // Apple adjustments from here
62 static const char * const gTypes
[] = {
75 "energy" // Apple addition, out of order, handle specially
78 static const char * const gSubTypes
[] = {
79 "g-force", // 0 acceleration
80 "arc-minute", // 1 angle
349 "day", // 270 duration
357 "centimeter", // 278 length
371 "stone", // Apple addition
372 "horsepower", // 293 power
375 "hectopascal", // 296 pressure
378 "kilometer-per-hour", // 299 speed
381 "celsius", // 302 temperature
383 "cubic-kilometer", // 304 volume
386 "calorie", // 307 energy Apple additions
393 MeasureUnit
*MeasureUnit::createGForce(UErrorCode
&status
) {
394 return MeasureUnit::create(0, 0, status
);
397 MeasureUnit
*MeasureUnit::createArcMinute(UErrorCode
&status
) {
398 return MeasureUnit::create(1, 0, status
);
401 MeasureUnit
*MeasureUnit::createArcSecond(UErrorCode
&status
) {
402 return MeasureUnit::create(1, 1, status
);
405 MeasureUnit
*MeasureUnit::createDegree(UErrorCode
&status
) {
406 return MeasureUnit::create(1, 2, status
);
409 MeasureUnit
*MeasureUnit::createAcre(UErrorCode
&status
) {
410 return MeasureUnit::create(2, 0, status
);
413 MeasureUnit
*MeasureUnit::createHectare(UErrorCode
&status
) {
414 return MeasureUnit::create(2, 1, status
);
417 MeasureUnit
*MeasureUnit::createSquareFoot(UErrorCode
&status
) {
418 return MeasureUnit::create(2, 2, status
);
421 MeasureUnit
*MeasureUnit::createSquareKilometer(UErrorCode
&status
) {
422 return MeasureUnit::create(2, 3, status
);
425 MeasureUnit
*MeasureUnit::createSquareMeter(UErrorCode
&status
) {
426 return MeasureUnit::create(2, 4, status
);
429 MeasureUnit
*MeasureUnit::createSquareMile(UErrorCode
&status
) {
430 return MeasureUnit::create(2, 5, status
);
433 MeasureUnit
*MeasureUnit::createDay(UErrorCode
&status
) {
434 return MeasureUnit::create(4, 0, status
);
437 MeasureUnit
*MeasureUnit::createHour(UErrorCode
&status
) {
438 return MeasureUnit::create(4, 1, status
);
441 MeasureUnit
*MeasureUnit::createMillisecond(UErrorCode
&status
) {
442 return MeasureUnit::create(4, 2, status
);
445 MeasureUnit
*MeasureUnit::createMinute(UErrorCode
&status
) {
446 return MeasureUnit::create(4, 3, status
);
449 MeasureUnit
*MeasureUnit::createMonth(UErrorCode
&status
) {
450 return MeasureUnit::create(4, 4, status
);
453 MeasureUnit
*MeasureUnit::createSecond(UErrorCode
&status
) {
454 return MeasureUnit::create(4, 5, status
);
457 MeasureUnit
*MeasureUnit::createWeek(UErrorCode
&status
) {
458 return MeasureUnit::create(4, 6, status
);
461 MeasureUnit
*MeasureUnit::createYear(UErrorCode
&status
) {
462 return MeasureUnit::create(4, 7, status
);
465 MeasureUnit
*MeasureUnit::createCentimeter(UErrorCode
&status
) {
466 return MeasureUnit::create(5, 0, status
);
469 MeasureUnit
*MeasureUnit::createFoot(UErrorCode
&status
) {
470 return MeasureUnit::create(5, 1, status
);
473 MeasureUnit
*MeasureUnit::createInch(UErrorCode
&status
) {
474 return MeasureUnit::create(5, 2, status
);
477 MeasureUnit
*MeasureUnit::createKilometer(UErrorCode
&status
) {
478 return MeasureUnit::create(5, 3, status
);
481 MeasureUnit
*MeasureUnit::createLightYear(UErrorCode
&status
) {
482 return MeasureUnit::create(5, 4, status
);
485 MeasureUnit
*MeasureUnit::createMeter(UErrorCode
&status
) {
486 return MeasureUnit::create(5, 5, status
);
489 MeasureUnit
*MeasureUnit::createMile(UErrorCode
&status
) {
490 return MeasureUnit::create(5, 6, status
);
493 MeasureUnit
*MeasureUnit::createMillimeter(UErrorCode
&status
) {
494 return MeasureUnit::create(5, 7, status
);
497 MeasureUnit
*MeasureUnit::createPicometer(UErrorCode
&status
) {
498 return MeasureUnit::create(5, 8, status
);
501 MeasureUnit
*MeasureUnit::createYard(UErrorCode
&status
) {
502 return MeasureUnit::create(5, 9, status
);
505 MeasureUnit
*MeasureUnit::createGram(UErrorCode
&status
) {
506 return MeasureUnit::create(6, 0, status
);
509 MeasureUnit
*MeasureUnit::createKilogram(UErrorCode
&status
) {
510 return MeasureUnit::create(6, 1, status
);
513 MeasureUnit
*MeasureUnit::createOunce(UErrorCode
&status
) {
514 return MeasureUnit::create(6, 2, status
);
517 MeasureUnit
*MeasureUnit::createPound(UErrorCode
&status
) {
518 return MeasureUnit::create(6, 3, status
);
521 MeasureUnit
*MeasureUnit::createStone(UErrorCode
&status
) {
522 return MeasureUnit::create(6, 4, status
);
525 MeasureUnit
*MeasureUnit::createHorsepower(UErrorCode
&status
) {
526 return MeasureUnit::create(7, 0, status
);
529 MeasureUnit
*MeasureUnit::createKilowatt(UErrorCode
&status
) {
530 return MeasureUnit::create(7, 1, status
);
533 MeasureUnit
*MeasureUnit::createWatt(UErrorCode
&status
) {
534 return MeasureUnit::create(7, 2, status
);
537 MeasureUnit
*MeasureUnit::createHectopascal(UErrorCode
&status
) {
538 return MeasureUnit::create(8, 0, status
);
541 MeasureUnit
*MeasureUnit::createInchHg(UErrorCode
&status
) {
542 return MeasureUnit::create(8, 1, status
);
545 MeasureUnit
*MeasureUnit::createMillibar(UErrorCode
&status
) {
546 return MeasureUnit::create(8, 2, status
);
549 MeasureUnit
*MeasureUnit::createKilometerPerHour(UErrorCode
&status
) {
550 return MeasureUnit::create(9, 0, status
);
553 MeasureUnit
*MeasureUnit::createMeterPerSecond(UErrorCode
&status
) {
554 return MeasureUnit::create(9, 1, status
);
557 MeasureUnit
*MeasureUnit::createMilePerHour(UErrorCode
&status
) {
558 return MeasureUnit::create(9, 2, status
);
561 MeasureUnit
*MeasureUnit::createCelsius(UErrorCode
&status
) {
562 return MeasureUnit::create(10, 0, status
);
565 MeasureUnit
*MeasureUnit::createFahrenheit(UErrorCode
&status
) {
566 return MeasureUnit::create(10, 1, status
);
569 MeasureUnit
*MeasureUnit::createCubicKilometer(UErrorCode
&status
) {
570 return MeasureUnit::create(11, 0, status
);
573 MeasureUnit
*MeasureUnit::createCubicMile(UErrorCode
&status
) {
574 return MeasureUnit::create(11, 1, status
);
577 MeasureUnit
*MeasureUnit::createLiter(UErrorCode
&status
) {
578 return MeasureUnit::create(11, 2, status
);
581 MeasureUnit
*MeasureUnit::createCalorie(UErrorCode
&status
) {
582 return MeasureUnit::create(12, 0, status
);
585 MeasureUnit
*MeasureUnit::createFoodcalorie(UErrorCode
&status
) {
586 return MeasureUnit::create(12, 1, status
);
589 MeasureUnit
*MeasureUnit::createJoule(UErrorCode
&status
) {
590 return MeasureUnit::create(12, 2, status
);
593 MeasureUnit
*MeasureUnit::createKilocalorie(UErrorCode
&status
) {
594 return MeasureUnit::create(12, 3, status
);
597 MeasureUnit
*MeasureUnit::createKilojoule(UErrorCode
&status
) {
598 return MeasureUnit::create(12, 4, status
);
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
);
619 MeasureUnit::MeasureUnit(const MeasureUnit
&other
)
620 : fTypeId(other
.fTypeId
), fSubTypeId(other
.fSubTypeId
) {
621 uprv_strcpy(fCurrency
, other
.fCurrency
);
624 MeasureUnit
&MeasureUnit::operator=(const MeasureUnit
&other
) {
625 if (this == &other
) {
628 fTypeId
= other
.fTypeId
;
629 fSubTypeId
= other
.fSubTypeId
;
630 uprv_strcpy(fCurrency
, other
.fCurrency
);
634 UObject
*MeasureUnit::clone() const {
635 return new MeasureUnit(*this);
638 MeasureUnit::~MeasureUnit() {
641 const char *MeasureUnit::getType() const {
642 return gTypes
[fTypeId
];
645 const char *MeasureUnit::getSubtype() const {
646 return fCurrency
[0] == 0 ? gSubTypes
[getOffset()] : fCurrency
;
649 UBool
MeasureUnit::operator==(const UObject
& other
) const {
650 if (this == &other
) { // Same object, equal
653 if (typeid(*this) != typeid(other
)) { // Different types, not equal
656 const MeasureUnit
&rhs
= static_cast<const MeasureUnit
&>(other
);
658 fTypeId
== rhs
.fTypeId
659 && fSubTypeId
== rhs
.fSubTypeId
660 && uprv_strcmp(fCurrency
, rhs
.fCurrency
) == 0);
663 int32_t MeasureUnit::getIndex() const {
664 return gIndexes
[fTypeId
] + fSubTypeId
;
667 int32_t MeasureUnit::getAvailable(
669 int32_t destCapacity
,
670 UErrorCode
&errorCode
) {
671 if (U_FAILURE(errorCode
)) {
674 if (destCapacity
< LENGTHOF(gSubTypes
)) {
675 errorCode
= U_BUFFER_OVERFLOW_ERROR
;
676 return LENGTHOF(gSubTypes
);
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
);
686 U_ASSERT(idx
== LENGTHOF(gSubTypes
));
687 return LENGTHOF(gSubTypes
);
690 int32_t MeasureUnit::getAvailable(
693 int32_t destCapacity
,
694 UErrorCode
&errorCode
) {
695 if (U_FAILURE(errorCode
)) {
698 int32_t typeIdx
= binarySearch(gTypes
, 0, LENGTHOF(gTypes
)-1, type
);
700 if (uprv_strcmp(type
, gTypes
[LENGTHOF(gTypes
)-1]) == 0) {
701 typeIdx
= LENGTHOF(gTypes
)-1;
706 int32_t len
= gOffsets
[typeIdx
+ 1] - gOffsets
[typeIdx
];
707 if (destCapacity
< len
) {
708 errorCode
= U_BUFFER_OVERFLOW_ERROR
;
711 for (int subTypeIdx
= 0; subTypeIdx
< len
; ++subTypeIdx
) {
712 dest
[subTypeIdx
].setTo(typeIdx
, subTypeIdx
);
717 StringEnumeration
* MeasureUnit::getAvailableTypes(UErrorCode
&errorCode
) {
718 UEnumeration
*uenum
= uenum_openCharStringsEnumeration(
719 gTypes
, LENGTHOF(gTypes
), &errorCode
);
720 if (U_FAILURE(errorCode
)) {
724 StringEnumeration
*result
= new UStringEnumeration(uenum
);
725 if (result
== NULL
) {
726 errorCode
= U_MEMORY_ALLOCATION_ERROR
;
733 int32_t MeasureUnit::getIndexCount() {
734 return gIndexes
[LENGTHOF(gIndexes
) - 1];
737 MeasureUnit
*MeasureUnit::create(int typeId
, int subTypeId
, UErrorCode
&status
) {
738 if (U_FAILURE(status
)) {
741 MeasureUnit
*result
= new MeasureUnit(typeId
, subTypeId
);
742 if (result
== NULL
) {
743 status
= U_MEMORY_ALLOCATION_ERROR
;
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);
752 result
= binarySearch(gSubTypes
, gOffsets
[fTypeId
], gOffsets
[fTypeId
+ 1], timeId
);
753 U_ASSERT(result
!= -1);
754 fSubTypeId
= result
- gOffsets
[fTypeId
];
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);
761 result
= binarySearch(
762 gSubTypes
, gOffsets
[fTypeId
], gOffsets
[fTypeId
+ 1], isoCurrency
);
764 fSubTypeId
= result
- gOffsets
[fTypeId
];
766 uprv_strncpy(fCurrency
, isoCurrency
, LENGTHOF(fCurrency
));
770 void MeasureUnit::setTo(int32_t typeId
, int32_t subTypeId
) {
772 fSubTypeId
= subTypeId
;
776 int32_t MeasureUnit::getOffset() const {
777 return gOffsets
[fTypeId
] + fSubTypeId
;
782 #endif /* !UNCONFIG_NO_FORMATTING */