| OLD | NEW |
| 1 /* | 1 /* |
| 2 ********************************************************************** | 2 ********************************************************************** |
| 3 * Copyright (c) 2004-2014, International Business Machines | 3 * Copyright (c) 2004-2015, International Business Machines |
| 4 * Corporation and others. All Rights Reserved. | 4 * Corporation and others. All Rights Reserved. |
| 5 ********************************************************************** | 5 ********************************************************************** |
| 6 * Author: Alan Liu | 6 * Author: Alan Liu |
| 7 * Created: April 20, 2004 | 7 * Created: April 20, 2004 |
| 8 * Since: ICU 3.0 | 8 * Since: ICU 3.0 |
| 9 ********************************************************************** | 9 ********************************************************************** |
| 10 */ | 10 */ |
| 11 #include "utypeinfo.h" // for 'typeid' to work | 11 #include "utypeinfo.h" // for 'typeid' to work |
| 12 #include "unicode/utypes.h" | 12 #include "unicode/utypes.h" |
| 13 | 13 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 30 #include "unicode/listformatter.h" | 30 #include "unicode/listformatter.h" |
| 31 #include "charstr.h" | 31 #include "charstr.h" |
| 32 #include "unicode/putil.h" | 32 #include "unicode/putil.h" |
| 33 #include "unicode/smpdtfmt.h" | 33 #include "unicode/smpdtfmt.h" |
| 34 #include "uassert.h" | 34 #include "uassert.h" |
| 35 | 35 |
| 36 #include "sharednumberformat.h" | 36 #include "sharednumberformat.h" |
| 37 #include "sharedpluralrules.h" | 37 #include "sharedpluralrules.h" |
| 38 #include "unifiedcache.h" | 38 #include "unifiedcache.h" |
| 39 | 39 |
| 40 #define MEAS_UNIT_COUNT 121 | 40 #define MEAS_UNIT_COUNT 129 |
| 41 #define WIDTH_INDEX_COUNT (UMEASFMT_WIDTH_NARROW + 1) | 41 #define WIDTH_INDEX_COUNT (UMEASFMT_WIDTH_NARROW + 1) |
| 42 | 42 |
| 43 U_NAMESPACE_BEGIN | 43 U_NAMESPACE_BEGIN |
| 44 | 44 |
| 45 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat) | 45 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat) |
| 46 | 46 |
| 47 // Used to format durations like 5:47 or 21:35:42. | 47 // Used to format durations like 5:47 or 21:35:42. |
| 48 class NumericDateFormatters : public UMemory { | 48 class NumericDateFormatters : public UMemory { |
| 49 public: | 49 public: |
| 50 // Formats like H:mm | 50 // Formats like H:mm |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 delete result; | 339 delete result; |
| 340 return NULL; | 340 return NULL; |
| 341 } | 341 } |
| 342 return result; | 342 return result; |
| 343 } | 343 } |
| 344 | 344 |
| 345 template<> U_I18N_API | 345 template<> U_I18N_API |
| 346 const MeasureFormatCacheData *LocaleCacheKey<MeasureFormatCacheData>::createObje
ct( | 346 const MeasureFormatCacheData *LocaleCacheKey<MeasureFormatCacheData>::createObje
ct( |
| 347 const void * /*unused*/, UErrorCode &status) const { | 347 const void * /*unused*/, UErrorCode &status) const { |
| 348 const char *localeId = fLoc.getName(); | 348 const char *localeId = fLoc.getName(); |
| 349 LocalUResourceBundlePointer topLevel(ures_open(NULL, localeId, &status)); | |
| 350 LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, localeId,
&status)); | 349 LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, localeId,
&status)); |
| 351 static UNumberFormatStyle currencyStyles[] = { | 350 static UNumberFormatStyle currencyStyles[] = { |
| 352 UNUM_CURRENCY_PLURAL, UNUM_CURRENCY_ISO, UNUM_CURRENCY}; | 351 UNUM_CURRENCY_PLURAL, UNUM_CURRENCY_ISO, UNUM_CURRENCY}; |
| 352 LocalPointer<MeasureFormatCacheData> result(new MeasureFormatCacheData(), st
atus); |
| 353 if (U_FAILURE(status)) { | 353 if (U_FAILURE(status)) { |
| 354 return NULL; | 354 return NULL; |
| 355 } | 355 } |
| 356 LocalPointer<MeasureFormatCacheData> result(new MeasureFormatCacheData()); | |
| 357 if (result.isNull()) { | |
| 358 status = U_MEMORY_ALLOCATION_ERROR; | |
| 359 return NULL; | |
| 360 } | |
| 361 if (!loadMeasureUnitData( | 356 if (!loadMeasureUnitData( |
| 362 unitsBundle.getAlias(), | 357 unitsBundle.getAlias(), |
| 363 *result, | 358 *result, |
| 364 status)) { | 359 status)) { |
| 365 return NULL; | 360 return NULL; |
| 366 } | 361 } |
| 367 result->adoptNumericDateFormatters(loadNumericDateFormatters( | 362 result->adoptNumericDateFormatters(loadNumericDateFormatters( |
| 368 topLevel.getAlias(), status)); | 363 unitsBundle.getAlias(), status)); |
| 369 if (U_FAILURE(status)) { | 364 if (U_FAILURE(status)) { |
| 370 return NULL; | 365 return NULL; |
| 371 } | 366 } |
| 372 | 367 |
| 373 for (int32_t i = 0; i < WIDTH_INDEX_COUNT; ++i) { | 368 for (int32_t i = 0; i < WIDTH_INDEX_COUNT; ++i) { |
| 374 result->adoptCurrencyFormat(i, NumberFormat::createInstance( | 369 result->adoptCurrencyFormat(i, NumberFormat::createInstance( |
| 375 localeId, currencyStyles[i], status)); | 370 localeId, currencyStyles[i], status)); |
| 376 if (U_FAILURE(status)) { | 371 if (U_FAILURE(status)) { |
| 377 return NULL; | 372 return NULL; |
| 378 } | 373 } |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 width = other.width; | 500 width = other.width; |
| 506 delete listFormatter; | 501 delete listFormatter; |
| 507 listFormatter = new ListFormatter(*other.listFormatter); | 502 listFormatter = new ListFormatter(*other.listFormatter); |
| 508 return *this; | 503 return *this; |
| 509 } | 504 } |
| 510 | 505 |
| 511 MeasureFormat::MeasureFormat() : | 506 MeasureFormat::MeasureFormat() : |
| 512 cache(NULL), | 507 cache(NULL), |
| 513 numberFormat(NULL), | 508 numberFormat(NULL), |
| 514 pluralRules(NULL), | 509 pluralRules(NULL), |
| 515 width(UMEASFMT_WIDTH_WIDE), | 510 width(UMEASFMT_WIDTH_SHORT), |
| 516 listFormatter(NULL) { | 511 listFormatter(NULL) { |
| 517 } | 512 } |
| 518 | 513 |
| 519 MeasureFormat::~MeasureFormat() { | 514 MeasureFormat::~MeasureFormat() { |
| 520 if (cache != NULL) { | 515 if (cache != NULL) { |
| 521 cache->removeRef(); | 516 cache->removeRef(); |
| 522 } | 517 } |
| 523 if (numberFormat != NULL) { | 518 if (numberFormat != NULL) { |
| 524 numberFormat->removeRef(); | 519 numberFormat->removeRef(); |
| 525 } | 520 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 return appendTo; | 582 return appendTo; |
| 588 } | 583 } |
| 589 | 584 |
| 590 void MeasureFormat::parseObject( | 585 void MeasureFormat::parseObject( |
| 591 const UnicodeString & /*source*/, | 586 const UnicodeString & /*source*/, |
| 592 Formattable & /*result*/, | 587 Formattable & /*result*/, |
| 593 ParsePosition& /*pos*/) const { | 588 ParsePosition& /*pos*/) const { |
| 594 return; | 589 return; |
| 595 } | 590 } |
| 596 | 591 |
| 597 UnicodeString &MeasureFormat::formatMeasuresPer( | 592 UnicodeString &MeasureFormat::formatMeasurePerUnit( |
| 598 const Measure *measures, | 593 const Measure &measure, |
| 599 int32_t measureCount, | |
| 600 const MeasureUnit &perUnit, | 594 const MeasureUnit &perUnit, |
| 601 UnicodeString &appendTo, | 595 UnicodeString &appendTo, |
| 602 FieldPosition &pos, | 596 FieldPosition &pos, |
| 603 UErrorCode &status) const { | 597 UErrorCode &status) const { |
| 598 if (U_FAILURE(status)) { |
| 599 return appendTo; |
| 600 } |
| 601 MeasureUnit *resolvedUnit = |
| 602 MeasureUnit::resolveUnitPerUnit(measure.getUnit(), perUnit); |
| 603 if (resolvedUnit != NULL) { |
| 604 Measure newMeasure(measure.getNumber(), resolvedUnit, status); |
| 605 return formatMeasure( |
| 606 newMeasure, **numberFormat, appendTo, pos, status); |
| 607 } |
| 604 FieldPosition fpos(pos.getField()); | 608 FieldPosition fpos(pos.getField()); |
| 605 UnicodeString measuresString; | 609 UnicodeString result; |
| 606 int32_t offset = withPerUnit( | 610 int32_t offset = withPerUnitAndAppend( |
| 607 formatMeasures( | 611 formatMeasure( |
| 608 measures, measureCount, measuresString, fpos, status), | 612 measure, **numberFormat, result, fpos, status), |
| 609 perUnit, | 613 perUnit, |
| 610 appendTo, | 614 appendTo, |
| 611 status); | 615 status); |
| 612 if (U_FAILURE(status)) { | 616 if (U_FAILURE(status)) { |
| 613 return appendTo; | 617 return appendTo; |
| 614 } | 618 } |
| 615 if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) { | 619 if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) { |
| 616 pos.setBeginIndex(fpos.getBeginIndex() + offset); | 620 pos.setBeginIndex(fpos.getBeginIndex() + offset); |
| 617 pos.setEndIndex(fpos.getEndIndex() + offset); | 621 pos.setEndIndex(fpos.getEndIndex() + offset); |
| 618 } | 622 } |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 return NULL; | 928 return NULL; |
| 925 } | 929 } |
| 926 const QuantityFormatter *formatters = | 930 const QuantityFormatter *formatters = |
| 927 cache->formatters[index]; | 931 cache->formatters[index]; |
| 928 if (formatters[widthIndex].isValid()) { | 932 if (formatters[widthIndex].isValid()) { |
| 929 return &formatters[widthIndex]; | 933 return &formatters[widthIndex]; |
| 930 } | 934 } |
| 931 if (formatters[UMEASFMT_WIDTH_SHORT].isValid()) { | 935 if (formatters[UMEASFMT_WIDTH_SHORT].isValid()) { |
| 932 return &formatters[UMEASFMT_WIDTH_SHORT]; | 936 return &formatters[UMEASFMT_WIDTH_SHORT]; |
| 933 } | 937 } |
| 934 if (formatters[UMEASFMT_WIDTH_WIDE].isValid()) { | |
| 935 return &formatters[UMEASFMT_WIDTH_WIDE]; | |
| 936 } | |
| 937 status = U_MISSING_RESOURCE_ERROR; | 938 status = U_MISSING_RESOURCE_ERROR; |
| 938 return NULL; | 939 return NULL; |
| 939 } | 940 } |
| 940 | 941 |
| 941 const SimplePatternFormatter *MeasureFormat::getPerUnitFormatter( | 942 const SimplePatternFormatter *MeasureFormat::getPerUnitFormatter( |
| 942 int32_t index, | 943 int32_t index, |
| 943 int32_t widthIndex) const { | 944 int32_t widthIndex) const { |
| 944 const SimplePatternFormatter * const * perUnitFormatters = | 945 const SimplePatternFormatter * const * perUnitFormatters = |
| 945 cache->getPerUnitFormattersByIndex(index); | 946 cache->getPerUnitFormattersByIndex(index); |
| 946 if (perUnitFormatters[widthIndex] != NULL) { | 947 if (perUnitFormatters[widthIndex] != NULL) { |
| 947 return perUnitFormatters[widthIndex]; | 948 return perUnitFormatters[widthIndex]; |
| 948 } | 949 } |
| 949 if (perUnitFormatters[UMEASFMT_WIDTH_SHORT] != NULL) { | 950 if (perUnitFormatters[UMEASFMT_WIDTH_SHORT] != NULL) { |
| 950 return perUnitFormatters[UMEASFMT_WIDTH_SHORT]; | 951 return perUnitFormatters[UMEASFMT_WIDTH_SHORT]; |
| 951 } | 952 } |
| 952 if (perUnitFormatters[UMEASFMT_WIDTH_WIDE] != NULL) { | |
| 953 return perUnitFormatters[UMEASFMT_WIDTH_WIDE]; | |
| 954 } | |
| 955 return NULL; | 953 return NULL; |
| 956 } | 954 } |
| 957 | 955 |
| 958 const SimplePatternFormatter *MeasureFormat::getPerFormatter( | 956 const SimplePatternFormatter *MeasureFormat::getPerFormatter( |
| 959 int32_t widthIndex, | 957 int32_t widthIndex, |
| 960 UErrorCode &status) const { | 958 UErrorCode &status) const { |
| 961 if (U_FAILURE(status)) { | 959 if (U_FAILURE(status)) { |
| 962 return NULL; | 960 return NULL; |
| 963 } | 961 } |
| 964 const SimplePatternFormatter * perFormatters = cache->perFormatters; | 962 const SimplePatternFormatter * perFormatters = cache->perFormatters; |
| 965 | 963 |
| 966 if (perFormatters[widthIndex].getPlaceholderCount() == 2) { | 964 if (perFormatters[widthIndex].getPlaceholderCount() == 2) { |
| 967 return &perFormatters[widthIndex]; | 965 return &perFormatters[widthIndex]; |
| 968 } | 966 } |
| 969 if (perFormatters[UMEASFMT_WIDTH_SHORT].getPlaceholderCount() == 2) { | 967 if (perFormatters[UMEASFMT_WIDTH_SHORT].getPlaceholderCount() == 2) { |
| 970 return &perFormatters[UMEASFMT_WIDTH_SHORT]; | 968 return &perFormatters[UMEASFMT_WIDTH_SHORT]; |
| 971 } | 969 } |
| 972 if (perFormatters[UMEASFMT_WIDTH_WIDE].getPlaceholderCount() == 2) { | |
| 973 return &perFormatters[UMEASFMT_WIDTH_WIDE]; | |
| 974 } | |
| 975 status = U_MISSING_RESOURCE_ERROR; | 970 status = U_MISSING_RESOURCE_ERROR; |
| 976 return NULL; | 971 return NULL; |
| 977 } | 972 } |
| 978 | 973 |
| 979 static void getPerUnitString( | 974 static void getPerUnitString( |
| 980 const QuantityFormatter &formatter, | 975 const QuantityFormatter &formatter, |
| 981 UnicodeString &result) { | 976 UnicodeString &result) { |
| 982 result = formatter.getByVariant("one")->getPatternWithNoPlaceholders(); | 977 result = formatter.getByVariant("one")->getPatternWithNoPlaceholders(); |
| 983 result.trim(); | 978 result.trim(); |
| 984 } | 979 } |
| 985 | 980 |
| 986 int32_t MeasureFormat::withPerUnit( | 981 int32_t MeasureFormat::withPerUnitAndAppend( |
| 987 const UnicodeString &formatted, | 982 const UnicodeString &formatted, |
| 988 const MeasureUnit &perUnit, | 983 const MeasureUnit &perUnit, |
| 989 UnicodeString &appendTo, | 984 UnicodeString &appendTo, |
| 990 UErrorCode &status) const { | 985 UErrorCode &status) const { |
| 991 int32_t offset = -1; | 986 int32_t offset = -1; |
| 992 if (U_FAILURE(status)) { | 987 if (U_FAILURE(status)) { |
| 993 return offset; | 988 return offset; |
| 994 } | 989 } |
| 995 const SimplePatternFormatter *perUnitFormatter = getPerUnitFormatter( | 990 const SimplePatternFormatter *perUnitFormatter = getPerUnitFormatter( |
| 996 perUnit.getIndex(), widthToIndex(width)); | 991 perUnit.getIndex(), widthToIndex(width)); |
| 997 if (perUnitFormatter != NULL) { | 992 if (perUnitFormatter != NULL) { |
| 998 const UnicodeString *params[] = {&formatted}; | 993 const UnicodeString *params[] = {&formatted}; |
| 999 perUnitFormatter->format( | 994 perUnitFormatter->formatAndAppend( |
| 1000 params, | 995 params, |
| 1001 UPRV_LENGTHOF(params), | 996 UPRV_LENGTHOF(params), |
| 1002 appendTo, | 997 appendTo, |
| 1003 &offset, | 998 &offset, |
| 1004 1, | 999 1, |
| 1005 status); | 1000 status); |
| 1006 return offset; | 1001 return offset; |
| 1007 } | 1002 } |
| 1008 const SimplePatternFormatter *perFormatter = getPerFormatter( | 1003 const SimplePatternFormatter *perFormatter = getPerFormatter( |
| 1009 widthToIndex(width), status); | 1004 widthToIndex(width), status); |
| 1010 const QuantityFormatter *qf = getQuantityFormatter( | 1005 const QuantityFormatter *qf = getQuantityFormatter( |
| 1011 perUnit.getIndex(), widthToIndex(width), status); | 1006 perUnit.getIndex(), widthToIndex(width), status); |
| 1012 if (U_FAILURE(status)) { | 1007 if (U_FAILURE(status)) { |
| 1013 return offset; | 1008 return offset; |
| 1014 } | 1009 } |
| 1015 UnicodeString perUnitString; | 1010 UnicodeString perUnitString; |
| 1016 getPerUnitString(*qf, perUnitString); | 1011 getPerUnitString(*qf, perUnitString); |
| 1017 const UnicodeString *params[] = {&formatted, &perUnitString}; | 1012 const UnicodeString *params[] = {&formatted, &perUnitString}; |
| 1018 perFormatter->format( | 1013 perFormatter->formatAndAppend( |
| 1019 params, | 1014 params, |
| 1020 UPRV_LENGTHOF(params), | 1015 UPRV_LENGTHOF(params), |
| 1021 appendTo, | 1016 appendTo, |
| 1022 &offset, | 1017 &offset, |
| 1023 1, | 1018 1, |
| 1024 status); | 1019 status); |
| 1025 return offset; | 1020 return offset; |
| 1026 } | 1021 } |
| 1027 | 1022 |
| 1028 UnicodeString &MeasureFormat::formatMeasuresSlowTrack( | 1023 UnicodeString &MeasureFormat::formatMeasuresSlowTrack( |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 MeasureFormat* U_EXPORT2 MeasureFormat::createCurrencyFormat(UErrorCode& ec) { | 1087 MeasureFormat* U_EXPORT2 MeasureFormat::createCurrencyFormat(UErrorCode& ec) { |
| 1093 if (U_FAILURE(ec)) { | 1088 if (U_FAILURE(ec)) { |
| 1094 return NULL; | 1089 return NULL; |
| 1095 } | 1090 } |
| 1096 return MeasureFormat::createCurrencyFormat(Locale::getDefault(), ec); | 1091 return MeasureFormat::createCurrencyFormat(Locale::getDefault(), ec); |
| 1097 } | 1092 } |
| 1098 | 1093 |
| 1099 U_NAMESPACE_END | 1094 U_NAMESPACE_END |
| 1100 | 1095 |
| 1101 #endif /* #if !UCONFIG_NO_FORMATTING */ | 1096 #endif /* #if !UCONFIG_NO_FORMATTING */ |
| OLD | NEW |