OLD | NEW |
1 /* | 1 /* |
2 ******************************************************************************* | 2 ******************************************************************************* |
3 * Copyright (C) 1997-2013, International Business Machines Corporation | 3 * Copyright (C) 1997-2014, International Business Machines Corporation |
4 * and others. All Rights Reserved. | 4 * and others. All Rights Reserved. |
5 ******************************************************************************* | 5 ******************************************************************************* |
6 */ | 6 */ |
7 | 7 |
| 8 #include "unicode/utypes.h" |
8 #include "utypeinfo.h" // for 'typeid' to work | 9 #include "utypeinfo.h" // for 'typeid' to work |
9 | 10 |
10 #include "unicode/rbnf.h" | 11 #include "unicode/rbnf.h" |
11 | 12 |
12 #if U_HAVE_RBNF | 13 #if U_HAVE_RBNF |
13 | 14 |
14 #include "unicode/normlzr.h" | 15 #include "unicode/normlzr.h" |
| 16 #include "unicode/plurfmt.h" |
15 #include "unicode/tblcoll.h" | 17 #include "unicode/tblcoll.h" |
16 #include "unicode/uchar.h" | 18 #include "unicode/uchar.h" |
17 #include "unicode/ucol.h" | 19 #include "unicode/ucol.h" |
18 #include "unicode/uloc.h" | 20 #include "unicode/uloc.h" |
19 #include "unicode/unum.h" | 21 #include "unicode/unum.h" |
20 #include "unicode/ures.h" | 22 #include "unicode/ures.h" |
21 #include "unicode/ustring.h" | 23 #include "unicode/ustring.h" |
22 #include "unicode/utf16.h" | 24 #include "unicode/utf16.h" |
23 #include "unicode/udata.h" | 25 #include "unicode/udata.h" |
| 26 #include "unicode/udisplaycontext.h" |
| 27 #include "unicode/brkiter.h" |
24 #include "nfrs.h" | 28 #include "nfrs.h" |
25 | 29 |
26 #include "cmemory.h" | 30 #include "cmemory.h" |
27 #include "cstring.h" | 31 #include "cstring.h" |
28 #include "patternprops.h" | 32 #include "patternprops.h" |
29 #include "uresimp.h" | 33 #include "uresimp.h" |
30 | 34 |
31 // debugging | 35 // debugging |
32 // #define DEBUG | 36 // #define RBNF_DEBUG |
33 | 37 |
34 #ifdef DEBUG | 38 #ifdef RBNF_DEBUG |
35 #include "stdio.h" | 39 #include "stdio.h" |
36 #endif | 40 #endif |
37 | 41 |
38 #define U_ICUDATA_RBNF U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "rbnf" | 42 #define U_ICUDATA_RBNF U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "rbnf" |
39 | 43 |
40 static const UChar gPercentPercent[] = | 44 static const UChar gPercentPercent[] = |
41 { | 45 { |
42 0x25, 0x25, 0 | 46 0x25, 0x25, 0 |
43 }; /* "%%" */ | 47 }; /* "%%" */ |
44 | 48 |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 while (*list && *list != c) ++list; return *list == c; | 321 while (*list && *list != c) ++list; return *list == c; |
318 } | 322 } |
319 void parseError(const char* msg); | 323 void parseError(const char* msg); |
320 | 324 |
321 StringLocalizationInfo* doParse(void); | 325 StringLocalizationInfo* doParse(void); |
322 | 326 |
323 UChar** nextArray(int32_t& requiredLength); | 327 UChar** nextArray(int32_t& requiredLength); |
324 UChar* nextString(void); | 328 UChar* nextString(void); |
325 }; | 329 }; |
326 | 330 |
327 #ifdef DEBUG | 331 #ifdef RBNF_DEBUG |
328 #define ERROR(msg) parseError(msg); return NULL; | 332 #define ERROR(msg) parseError(msg); return NULL; |
| 333 #define EXPLANATION_ARG explanationArg |
329 #else | 334 #else |
330 #define ERROR(msg) parseError(NULL); return NULL; | 335 #define ERROR(msg) parseError(NULL); return NULL; |
| 336 #define EXPLANATION_ARG |
331 #endif | 337 #endif |
332 | 338 |
333 | 339 |
334 static const UChar DQUOTE_STOPLIST[] = { | 340 static const UChar DQUOTE_STOPLIST[] = { |
335 QUOTE, 0 | 341 QUOTE, 0 |
336 }; | 342 }; |
337 | 343 |
338 static const UChar SQUOTE_STOPLIST[] = { | 344 static const UChar SQUOTE_STOPLIST[] = { |
339 TICK, 0 | 345 TICK, 0 |
340 }; | 346 }; |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 inc(); | 524 inc(); |
519 } else if (x == OPEN_ANGLE || x == TICK || x == QUOTE) { | 525 } else if (x == OPEN_ANGLE || x == TICK || x == QUOTE) { |
520 ERROR("Unexpected character in string"); | 526 ERROR("Unexpected character in string"); |
521 } | 527 } |
522 } | 528 } |
523 | 529 |
524 // ok for there to be no next string | 530 // ok for there to be no next string |
525 return result; | 531 return result; |
526 } | 532 } |
527 | 533 |
528 void | 534 void LocDataParser::parseError(const char* EXPLANATION_ARG) |
529 LocDataParser::parseError(const char* /*str*/) { | 535 { |
530 if (!data) { | 536 if (!data) { |
531 return; | 537 return; |
532 } | 538 } |
533 | 539 |
534 const UChar* start = p - U_PARSE_CONTEXT_LEN - 1; | 540 const UChar* start = p - U_PARSE_CONTEXT_LEN - 1; |
535 if (start < data) { | 541 if (start < data) { |
536 start = data; | 542 start = data; |
537 } | 543 } |
538 for (UChar* x = p; --x >= start;) { | 544 for (UChar* x = p; --x >= start;) { |
539 if (!*x) { | 545 if (!*x) { |
540 start = x+1; | 546 start = x+1; |
541 break; | 547 break; |
542 } | 548 } |
543 } | 549 } |
544 const UChar* limit = p + U_PARSE_CONTEXT_LEN - 1; | 550 const UChar* limit = p + U_PARSE_CONTEXT_LEN - 1; |
545 if (limit > e) { | 551 if (limit > e) { |
546 limit = e; | 552 limit = e; |
547 } | 553 } |
548 u_strncpy(pe.preContext, start, (int32_t)(p-start)); | 554 u_strncpy(pe.preContext, start, (int32_t)(p-start)); |
549 pe.preContext[p-start] = 0; | 555 pe.preContext[p-start] = 0; |
550 u_strncpy(pe.postContext, p, (int32_t)(limit-p)); | 556 u_strncpy(pe.postContext, p, (int32_t)(limit-p)); |
551 pe.postContext[limit-p] = 0; | 557 pe.postContext[limit-p] = 0; |
552 pe.offset = (int32_t)(p - data); | 558 pe.offset = (int32_t)(p - data); |
553 | 559 |
554 #ifdef DEBUG | 560 #ifdef RBNF_DEBUG |
555 fprintf(stderr, "%s at or near character %d: ", str, p-data); | 561 fprintf(stderr, "%s at or near character %ld: ", EXPLANATION_ARG, p-data); |
556 | 562 |
557 UnicodeString msg; | 563 UnicodeString msg; |
558 msg.append(start, p - start); | 564 msg.append(start, p - start); |
559 msg.append((UChar)0x002f); /* SOLIDUS/SLASH */ | 565 msg.append((UChar)0x002f); /* SOLIDUS/SLASH */ |
560 msg.append(p, limit-p); | 566 msg.append(p, limit-p); |
561 msg.append("'"); | 567 msg.append(UNICODE_STRING_SIMPLE("'")); |
562 | 568 |
563 char buf[128]; | 569 char buf[128]; |
564 int32_t len = msg.extract(0, msg.length(), buf, 128); | 570 int32_t len = msg.extract(0, msg.length(), buf, 128); |
565 if (len >= 128) { | 571 if (len >= 128) { |
566 buf[127] = 0; | 572 buf[127] = 0; |
567 } else { | 573 } else { |
568 buf[len] = 0; | 574 buf[len] = 0; |
569 } | 575 } |
570 fprintf(stderr, "%s\n", buf); | 576 fprintf(stderr, "%s\n", buf); |
571 fflush(stderr); | 577 fflush(stderr); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 : ruleSets(NULL) | 657 : ruleSets(NULL) |
652 , ruleSetDescriptions(NULL) | 658 , ruleSetDescriptions(NULL) |
653 , numRuleSets(0) | 659 , numRuleSets(0) |
654 , defaultRuleSet(NULL) | 660 , defaultRuleSet(NULL) |
655 , locale(alocale) | 661 , locale(alocale) |
656 , collator(NULL) | 662 , collator(NULL) |
657 , decimalFormatSymbols(NULL) | 663 , decimalFormatSymbols(NULL) |
658 , lenient(FALSE) | 664 , lenient(FALSE) |
659 , lenientParseRules(NULL) | 665 , lenientParseRules(NULL) |
660 , localizations(NULL) | 666 , localizations(NULL) |
| 667 , capitalizationInfoSet(FALSE) |
| 668 , capitalizationForUIListMenu(FALSE) |
| 669 , capitalizationForStandAlone(FALSE) |
| 670 , capitalizationBrkIter(NULL) |
661 { | 671 { |
662 LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, statu
s); | 672 LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, statu
s); |
663 init(description, locinfo, perror, status); | 673 init(description, locinfo, perror, status); |
664 } | 674 } |
665 | 675 |
666 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, | 676 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, |
667 const UnicodeString& locs, | 677 const UnicodeString& locs, |
668 UParseError& perror, UErrorCode& st
atus) | 678 UParseError& perror, UErrorCode& st
atus) |
669 : ruleSets(NULL) | 679 : ruleSets(NULL) |
670 , ruleSetDescriptions(NULL) | 680 , ruleSetDescriptions(NULL) |
671 , numRuleSets(0) | 681 , numRuleSets(0) |
672 , defaultRuleSet(NULL) | 682 , defaultRuleSet(NULL) |
673 , locale(Locale::getDefault()) | 683 , locale(Locale::getDefault()) |
674 , collator(NULL) | 684 , collator(NULL) |
675 , decimalFormatSymbols(NULL) | 685 , decimalFormatSymbols(NULL) |
676 , lenient(FALSE) | 686 , lenient(FALSE) |
677 , lenientParseRules(NULL) | 687 , lenientParseRules(NULL) |
678 , localizations(NULL) | 688 , localizations(NULL) |
| 689 , capitalizationInfoSet(FALSE) |
| 690 , capitalizationForUIListMenu(FALSE) |
| 691 , capitalizationForStandAlone(FALSE) |
| 692 , capitalizationBrkIter(NULL) |
679 { | 693 { |
680 LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, statu
s); | 694 LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, statu
s); |
681 init(description, locinfo, perror, status); | 695 init(description, locinfo, perror, status); |
682 } | 696 } |
683 | 697 |
684 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, | 698 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, |
685 LocalizationInfo* info, | 699 LocalizationInfo* info, |
686 const Locale& alocale, UParseError&
perror, UErrorCode& status) | 700 const Locale& alocale, UParseError&
perror, UErrorCode& status) |
687 : ruleSets(NULL) | 701 : ruleSets(NULL) |
688 , ruleSetDescriptions(NULL) | 702 , ruleSetDescriptions(NULL) |
689 , numRuleSets(0) | 703 , numRuleSets(0) |
690 , defaultRuleSet(NULL) | 704 , defaultRuleSet(NULL) |
691 , locale(alocale) | 705 , locale(alocale) |
692 , collator(NULL) | 706 , collator(NULL) |
693 , decimalFormatSymbols(NULL) | 707 , decimalFormatSymbols(NULL) |
694 , lenient(FALSE) | 708 , lenient(FALSE) |
695 , lenientParseRules(NULL) | 709 , lenientParseRules(NULL) |
696 , localizations(NULL) | 710 , localizations(NULL) |
| 711 , capitalizationInfoSet(FALSE) |
| 712 , capitalizationForUIListMenu(FALSE) |
| 713 , capitalizationForStandAlone(FALSE) |
| 714 , capitalizationBrkIter(NULL) |
697 { | 715 { |
698 init(description, info, perror, status); | 716 init(description, info, perror, status); |
699 } | 717 } |
700 | 718 |
701 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, | 719 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, |
702 UParseError& perror, | 720 UParseError& perror, |
703 UErrorCode& status) | 721 UErrorCode& status) |
704 : ruleSets(NULL) | 722 : ruleSets(NULL) |
705 , ruleSetDescriptions(NULL) | 723 , ruleSetDescriptions(NULL) |
706 , numRuleSets(0) | 724 , numRuleSets(0) |
707 , defaultRuleSet(NULL) | 725 , defaultRuleSet(NULL) |
708 , locale(Locale::getDefault()) | 726 , locale(Locale::getDefault()) |
709 , collator(NULL) | 727 , collator(NULL) |
710 , decimalFormatSymbols(NULL) | 728 , decimalFormatSymbols(NULL) |
711 , lenient(FALSE) | 729 , lenient(FALSE) |
712 , lenientParseRules(NULL) | 730 , lenientParseRules(NULL) |
713 , localizations(NULL) | 731 , localizations(NULL) |
| 732 , capitalizationInfoSet(FALSE) |
| 733 , capitalizationForUIListMenu(FALSE) |
| 734 , capitalizationForStandAlone(FALSE) |
| 735 , capitalizationBrkIter(NULL) |
714 { | 736 { |
715 init(description, NULL, perror, status); | 737 init(description, NULL, perror, status); |
716 } | 738 } |
717 | 739 |
718 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, | 740 RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, |
719 const Locale& aLocale, | 741 const Locale& aLocale, |
720 UParseError& perror, | 742 UParseError& perror, |
721 UErrorCode& status) | 743 UErrorCode& status) |
722 : ruleSets(NULL) | 744 : ruleSets(NULL) |
723 , ruleSetDescriptions(NULL) | 745 , ruleSetDescriptions(NULL) |
724 , numRuleSets(0) | 746 , numRuleSets(0) |
725 , defaultRuleSet(NULL) | 747 , defaultRuleSet(NULL) |
726 , locale(aLocale) | 748 , locale(aLocale) |
727 , collator(NULL) | 749 , collator(NULL) |
728 , decimalFormatSymbols(NULL) | 750 , decimalFormatSymbols(NULL) |
729 , lenient(FALSE) | 751 , lenient(FALSE) |
730 , lenientParseRules(NULL) | 752 , lenientParseRules(NULL) |
731 , localizations(NULL) | 753 , localizations(NULL) |
| 754 , capitalizationInfoSet(FALSE) |
| 755 , capitalizationForUIListMenu(FALSE) |
| 756 , capitalizationForStandAlone(FALSE) |
| 757 , capitalizationBrkIter(NULL) |
732 { | 758 { |
733 init(description, NULL, perror, status); | 759 init(description, NULL, perror, status); |
734 } | 760 } |
735 | 761 |
736 RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale&
alocale, UErrorCode& status) | 762 RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale&
alocale, UErrorCode& status) |
737 : ruleSets(NULL) | 763 : ruleSets(NULL) |
738 , ruleSetDescriptions(NULL) | 764 , ruleSetDescriptions(NULL) |
739 , numRuleSets(0) | 765 , numRuleSets(0) |
740 , defaultRuleSet(NULL) | 766 , defaultRuleSet(NULL) |
741 , locale(alocale) | 767 , locale(alocale) |
742 , collator(NULL) | 768 , collator(NULL) |
743 , decimalFormatSymbols(NULL) | 769 , decimalFormatSymbols(NULL) |
744 , lenient(FALSE) | 770 , lenient(FALSE) |
745 , lenientParseRules(NULL) | 771 , lenientParseRules(NULL) |
746 , localizations(NULL) | 772 , localizations(NULL) |
| 773 , capitalizationInfoSet(FALSE) |
| 774 , capitalizationForUIListMenu(FALSE) |
| 775 , capitalizationForStandAlone(FALSE) |
| 776 , capitalizationBrkIter(NULL) |
747 { | 777 { |
748 if (U_FAILURE(status)) { | 778 if (U_FAILURE(status)) { |
749 return; | 779 return; |
750 } | 780 } |
751 | 781 |
752 const char* rules_tag = "RBNFRules"; | 782 const char* rules_tag = "RBNFRules"; |
753 const char* fmt_tag = ""; | 783 const char* fmt_tag = ""; |
754 switch (tag) { | 784 switch (tag) { |
755 case URBNF_SPELLOUT: fmt_tag = "SpelloutRules"; break; | 785 case URBNF_SPELLOUT: fmt_tag = "SpelloutRules"; break; |
756 case URBNF_ORDINAL: fmt_tag = "OrdinalRules"; break; | 786 case URBNF_ORDINAL: fmt_tag = "OrdinalRules"; break; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 , ruleSets(NULL) | 827 , ruleSets(NULL) |
798 , ruleSetDescriptions(NULL) | 828 , ruleSetDescriptions(NULL) |
799 , numRuleSets(0) | 829 , numRuleSets(0) |
800 , defaultRuleSet(NULL) | 830 , defaultRuleSet(NULL) |
801 , locale(rhs.locale) | 831 , locale(rhs.locale) |
802 , collator(NULL) | 832 , collator(NULL) |
803 , decimalFormatSymbols(NULL) | 833 , decimalFormatSymbols(NULL) |
804 , lenient(FALSE) | 834 , lenient(FALSE) |
805 , lenientParseRules(NULL) | 835 , lenientParseRules(NULL) |
806 , localizations(NULL) | 836 , localizations(NULL) |
| 837 , capitalizationInfoSet(FALSE) |
| 838 , capitalizationForUIListMenu(FALSE) |
| 839 , capitalizationForStandAlone(FALSE) |
| 840 , capitalizationBrkIter(NULL) |
807 { | 841 { |
808 this->operator=(rhs); | 842 this->operator=(rhs); |
809 } | 843 } |
810 | 844 |
811 // -------- | 845 // -------- |
812 | 846 |
813 RuleBasedNumberFormat& | 847 RuleBasedNumberFormat& |
814 RuleBasedNumberFormat::operator=(const RuleBasedNumberFormat& rhs) | 848 RuleBasedNumberFormat::operator=(const RuleBasedNumberFormat& rhs) |
815 { | 849 { |
| 850 if (this == &rhs) { |
| 851 return *this; |
| 852 } |
| 853 NumberFormat::operator=(rhs); |
816 UErrorCode status = U_ZERO_ERROR; | 854 UErrorCode status = U_ZERO_ERROR; |
817 dispose(); | 855 dispose(); |
818 locale = rhs.locale; | 856 locale = rhs.locale; |
819 lenient = rhs.lenient; | 857 lenient = rhs.lenient; |
820 | 858 |
821 UnicodeString rules = rhs.getRules(); | |
822 UParseError perror; | 859 UParseError perror; |
823 init(rules, rhs.localizations ? rhs.localizations->ref() : NULL, perror, sta
tus); | 860 init(rhs.originalDescription, rhs.localizations ? rhs.localizations->ref() :
NULL, perror, status); |
| 861 setDecimalFormatSymbols(*rhs.getDecimalFormatSymbols()); |
| 862 setDefaultRuleSet(rhs.getDefaultRuleSetName(), status); |
| 863 |
| 864 capitalizationInfoSet = rhs.capitalizationInfoSet; |
| 865 capitalizationForUIListMenu = rhs.capitalizationForUIListMenu; |
| 866 capitalizationForStandAlone = rhs.capitalizationForStandAlone; |
| 867 #if !UCONFIG_NO_BREAK_ITERATION |
| 868 capitalizationBrkIter = (rhs.capitalizationBrkIter!=NULL)? rhs.capitalizatio
nBrkIter->clone(): NULL; |
| 869 #endif |
824 | 870 |
825 return *this; | 871 return *this; |
826 } | 872 } |
827 | 873 |
828 RuleBasedNumberFormat::~RuleBasedNumberFormat() | 874 RuleBasedNumberFormat::~RuleBasedNumberFormat() |
829 { | 875 { |
830 dispose(); | 876 dispose(); |
831 } | 877 } |
832 | 878 |
833 Format* | 879 Format* |
834 RuleBasedNumberFormat::clone(void) const | 880 RuleBasedNumberFormat::clone(void) const |
835 { | 881 { |
836 RuleBasedNumberFormat * result = NULL; | 882 return new RuleBasedNumberFormat(*this); |
837 UnicodeString rules = getRules(); | |
838 UErrorCode status = U_ZERO_ERROR; | |
839 UParseError perror; | |
840 result = new RuleBasedNumberFormat(rules, localizations, locale, perror, sta
tus); | |
841 /* test for NULL */ | |
842 if (result == 0) { | |
843 status = U_MEMORY_ALLOCATION_ERROR; | |
844 return 0; | |
845 } | |
846 if (U_FAILURE(status)) { | |
847 delete result; | |
848 result = 0; | |
849 } else { | |
850 result->lenient = lenient; | |
851 } | |
852 return result; | |
853 } | 883 } |
854 | 884 |
855 UBool | 885 UBool |
856 RuleBasedNumberFormat::operator==(const Format& other) const | 886 RuleBasedNumberFormat::operator==(const Format& other) const |
857 { | 887 { |
858 if (this == &other) { | 888 if (this == &other) { |
859 return TRUE; | 889 return TRUE; |
860 } | 890 } |
861 | 891 |
862 if (typeid(*this) == typeid(other)) { | 892 if (typeid(*this) == typeid(other)) { |
863 const RuleBasedNumberFormat& rhs = (const RuleBasedNumberFormat&)other; | 893 const RuleBasedNumberFormat& rhs = (const RuleBasedNumberFormat&)other; |
| 894 // test for capitalization info equality is adequately handled |
| 895 // by the NumberFormat test for fCapitalizationContext equality; |
| 896 // the info here is just derived from that. |
864 if (locale == rhs.locale && | 897 if (locale == rhs.locale && |
865 lenient == rhs.lenient && | 898 lenient == rhs.lenient && |
866 (localizations == NULL | 899 (localizations == NULL |
867 ? rhs.localizations == NULL | 900 ? rhs.localizations == NULL |
868 : (rhs.localizations == NULL | 901 : (rhs.localizations == NULL |
869 ? FALSE | 902 ? FALSE |
870 : *localizations == rhs.localizations))) { | 903 : *localizations == rhs.localizations))) { |
871 | 904 |
872 NFRuleSet** p = ruleSets; | 905 NFRuleSet** p = ruleSets; |
873 NFRuleSet** q = rhs.ruleSets; | 906 NFRuleSet** q = rhs.ruleSets; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 status = U_ILLEGAL_ARGUMENT_ERROR; | 1058 status = U_ILLEGAL_ARGUMENT_ERROR; |
1026 } | 1059 } |
1027 return NULL; | 1060 return NULL; |
1028 } | 1061 } |
1029 | 1062 |
1030 UnicodeString& | 1063 UnicodeString& |
1031 RuleBasedNumberFormat::format(int32_t number, | 1064 RuleBasedNumberFormat::format(int32_t number, |
1032 UnicodeString& toAppendTo, | 1065 UnicodeString& toAppendTo, |
1033 FieldPosition& /* pos */) const | 1066 FieldPosition& /* pos */) const |
1034 { | 1067 { |
1035 if (defaultRuleSet) defaultRuleSet->format((int64_t)number, toAppendTo, toAp
pendTo.length()); | 1068 if (defaultRuleSet) { |
| 1069 UErrorCode status = U_ZERO_ERROR; |
| 1070 int32_t startPos = toAppendTo.length(); |
| 1071 defaultRuleSet->format((int64_t)number, toAppendTo, toAppendTo.length(),
status); |
| 1072 adjustForCapitalizationContext(startPos, toAppendTo); |
| 1073 } |
1036 return toAppendTo; | 1074 return toAppendTo; |
1037 } | 1075 } |
1038 | 1076 |
1039 | 1077 |
1040 UnicodeString& | 1078 UnicodeString& |
1041 RuleBasedNumberFormat::format(int64_t number, | 1079 RuleBasedNumberFormat::format(int64_t number, |
1042 UnicodeString& toAppendTo, | 1080 UnicodeString& toAppendTo, |
1043 FieldPosition& /* pos */) const | 1081 FieldPosition& /* pos */) const |
1044 { | 1082 { |
1045 if (defaultRuleSet) defaultRuleSet->format(number, toAppendTo, toAppendTo.le
ngth()); | 1083 if (defaultRuleSet) { |
| 1084 UErrorCode status = U_ZERO_ERROR; |
| 1085 int32_t startPos = toAppendTo.length(); |
| 1086 defaultRuleSet->format(number, toAppendTo, toAppendTo.length(), status); |
| 1087 adjustForCapitalizationContext(startPos, toAppendTo); |
| 1088 } |
1046 return toAppendTo; | 1089 return toAppendTo; |
1047 } | 1090 } |
1048 | 1091 |
1049 | 1092 |
1050 UnicodeString& | 1093 UnicodeString& |
1051 RuleBasedNumberFormat::format(double number, | 1094 RuleBasedNumberFormat::format(double number, |
1052 UnicodeString& toAppendTo, | 1095 UnicodeString& toAppendTo, |
1053 FieldPosition& /* pos */) const | 1096 FieldPosition& /* pos */) const |
1054 { | 1097 { |
| 1098 int32_t startPos = toAppendTo.length(); |
1055 // Special case for NaN; adapted from what DecimalFormat::_format( double nu
mber,...) does. | 1099 // Special case for NaN; adapted from what DecimalFormat::_format( double nu
mber,...) does. |
1056 if (uprv_isNaN(number)) { | 1100 if (uprv_isNaN(number)) { |
1057 DecimalFormatSymbols* decFmtSyms = getDecimalFormatSymbols(); // RuleBas
edNumberFormat internal | 1101 DecimalFormatSymbols* decFmtSyms = getDecimalFormatSymbols(); // RuleBas
edNumberFormat internal |
1058 if (decFmtSyms) { | 1102 if (decFmtSyms) { |
1059 toAppendTo += decFmtSyms->getConstSymbol(DecimalFormatSymbols::kNaNS
ymbol); | 1103 toAppendTo += decFmtSyms->getConstSymbol(DecimalFormatSymbols::kNaNS
ymbol); |
1060 } | 1104 } |
1061 } else if (defaultRuleSet) { | 1105 } else if (defaultRuleSet) { |
1062 defaultRuleSet->format(number, toAppendTo, toAppendTo.length()); | 1106 UErrorCode status = U_ZERO_ERROR; |
| 1107 defaultRuleSet->format(number, toAppendTo, toAppendTo.length(), status); |
1063 } | 1108 } |
1064 return toAppendTo; | 1109 return adjustForCapitalizationContext(startPos, toAppendTo); |
1065 } | 1110 } |
1066 | 1111 |
1067 | 1112 |
1068 UnicodeString& | 1113 UnicodeString& |
1069 RuleBasedNumberFormat::format(int32_t number, | 1114 RuleBasedNumberFormat::format(int32_t number, |
1070 const UnicodeString& ruleSetName, | 1115 const UnicodeString& ruleSetName, |
1071 UnicodeString& toAppendTo, | 1116 UnicodeString& toAppendTo, |
1072 FieldPosition& /* pos */, | 1117 FieldPosition& /* pos */, |
1073 UErrorCode& status) const | 1118 UErrorCode& status) const |
1074 { | 1119 { |
1075 // return format((int64_t)number, ruleSetName, toAppendTo, pos, status); | 1120 // return format((int64_t)number, ruleSetName, toAppendTo, pos, status); |
1076 if (U_SUCCESS(status)) { | 1121 if (U_SUCCESS(status)) { |
1077 if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) { | 1122 if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) { |
1078 // throw new IllegalArgumentException("Can't use internal rule set")
; | 1123 // throw new IllegalArgumentException("Can't use internal rule set")
; |
1079 status = U_ILLEGAL_ARGUMENT_ERROR; | 1124 status = U_ILLEGAL_ARGUMENT_ERROR; |
1080 } else { | 1125 } else { |
1081 NFRuleSet *rs = findRuleSet(ruleSetName, status); | 1126 NFRuleSet *rs = findRuleSet(ruleSetName, status); |
1082 if (rs) { | 1127 if (rs) { |
1083 rs->format((int64_t)number, toAppendTo, toAppendTo.length()); | 1128 int32_t startPos = toAppendTo.length(); |
| 1129 rs->format((int64_t)number, toAppendTo, toAppendTo.length(), sta
tus); |
| 1130 adjustForCapitalizationContext(startPos, toAppendTo); |
1084 } | 1131 } |
1085 } | 1132 } |
1086 } | 1133 } |
1087 return toAppendTo; | 1134 return toAppendTo; |
1088 } | 1135 } |
1089 | 1136 |
1090 | 1137 |
1091 UnicodeString& | 1138 UnicodeString& |
1092 RuleBasedNumberFormat::format(int64_t number, | 1139 RuleBasedNumberFormat::format(int64_t number, |
1093 const UnicodeString& ruleSetName, | 1140 const UnicodeString& ruleSetName, |
1094 UnicodeString& toAppendTo, | 1141 UnicodeString& toAppendTo, |
1095 FieldPosition& /* pos */, | 1142 FieldPosition& /* pos */, |
1096 UErrorCode& status) const | 1143 UErrorCode& status) const |
1097 { | 1144 { |
1098 if (U_SUCCESS(status)) { | 1145 if (U_SUCCESS(status)) { |
1099 if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) { | 1146 if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) { |
1100 // throw new IllegalArgumentException("Can't use internal rule set")
; | 1147 // throw new IllegalArgumentException("Can't use internal rule set")
; |
1101 status = U_ILLEGAL_ARGUMENT_ERROR; | 1148 status = U_ILLEGAL_ARGUMENT_ERROR; |
1102 } else { | 1149 } else { |
1103 NFRuleSet *rs = findRuleSet(ruleSetName, status); | 1150 NFRuleSet *rs = findRuleSet(ruleSetName, status); |
1104 if (rs) { | 1151 if (rs) { |
1105 rs->format(number, toAppendTo, toAppendTo.length()); | 1152 int32_t startPos = toAppendTo.length(); |
| 1153 rs->format(number, toAppendTo, toAppendTo.length(), status); |
| 1154 adjustForCapitalizationContext(startPos, toAppendTo); |
1106 } | 1155 } |
1107 } | 1156 } |
1108 } | 1157 } |
1109 return toAppendTo; | 1158 return toAppendTo; |
1110 } | 1159 } |
1111 | 1160 |
1112 | 1161 |
1113 UnicodeString& | 1162 UnicodeString& |
1114 RuleBasedNumberFormat::format(double number, | 1163 RuleBasedNumberFormat::format(double number, |
1115 const UnicodeString& ruleSetName, | 1164 const UnicodeString& ruleSetName, |
1116 UnicodeString& toAppendTo, | 1165 UnicodeString& toAppendTo, |
1117 FieldPosition& /* pos */, | 1166 FieldPosition& /* pos */, |
1118 UErrorCode& status) const | 1167 UErrorCode& status) const |
1119 { | 1168 { |
1120 if (U_SUCCESS(status)) { | 1169 if (U_SUCCESS(status)) { |
1121 if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) { | 1170 if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) { |
1122 // throw new IllegalArgumentException("Can't use internal rule set")
; | 1171 // throw new IllegalArgumentException("Can't use internal rule set")
; |
1123 status = U_ILLEGAL_ARGUMENT_ERROR; | 1172 status = U_ILLEGAL_ARGUMENT_ERROR; |
1124 } else { | 1173 } else { |
1125 NFRuleSet *rs = findRuleSet(ruleSetName, status); | 1174 NFRuleSet *rs = findRuleSet(ruleSetName, status); |
1126 if (rs) { | 1175 if (rs) { |
1127 rs->format(number, toAppendTo, toAppendTo.length()); | 1176 int32_t startPos = toAppendTo.length(); |
| 1177 rs->format(number, toAppendTo, toAppendTo.length(), status); |
| 1178 adjustForCapitalizationContext(startPos, toAppendTo); |
1128 } | 1179 } |
1129 } | 1180 } |
1130 } | 1181 } |
1131 return toAppendTo; | 1182 return toAppendTo; |
1132 } | 1183 } |
1133 | 1184 |
| 1185 UnicodeString& |
| 1186 RuleBasedNumberFormat::adjustForCapitalizationContext(int32_t startPos, |
| 1187 UnicodeString& currentResu
lt) const |
| 1188 { |
| 1189 #if !UCONFIG_NO_BREAK_ITERATION |
| 1190 if (startPos==0 && currentResult.length() > 0) { |
| 1191 // capitalize currentResult according to context |
| 1192 UChar32 ch = currentResult.char32At(0); |
| 1193 UErrorCode status = U_ZERO_ERROR; |
| 1194 UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITAL
IZATION, status); |
| 1195 if ( u_islower(ch) && U_SUCCESS(status) && capitalizationBrkIter!= NULL
&& |
| 1196 ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_
SENTENCE || |
| 1197 (capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_M
ENU && capitalizationForUIListMenu) || |
| 1198 (capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_STANDALONE &
& capitalizationForStandAlone)) ) { |
| 1199 // titlecase first word of currentResult, here use sentence iterator
unlike current implementations |
| 1200 // in LocaleDisplayNamesImpl::adjustForUsageAndContext and RelativeD
ateFormat::format |
| 1201 currentResult.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_
LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); |
| 1202 } |
| 1203 } |
| 1204 #endif |
| 1205 return currentResult; |
| 1206 } |
| 1207 |
| 1208 |
1134 void | 1209 void |
1135 RuleBasedNumberFormat::parse(const UnicodeString& text, | 1210 RuleBasedNumberFormat::parse(const UnicodeString& text, |
1136 Formattable& result, | 1211 Formattable& result, |
1137 ParsePosition& parsePosition) const | 1212 ParsePosition& parsePosition) const |
1138 { | 1213 { |
1139 if (!ruleSets) { | 1214 if (!ruleSets) { |
1140 parsePosition.setErrorIndex(0); | 1215 parsePosition.setErrorIndex(0); |
1141 return; | 1216 return; |
1142 } | 1217 } |
1143 | 1218 |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1422 if (rs == NULL) { | 1497 if (rs == NULL) { |
1423 break; // error | 1498 break; // error |
1424 } | 1499 } |
1425 if (i == 0) { | 1500 if (i == 0) { |
1426 defaultRuleSet = rs; | 1501 defaultRuleSet = rs; |
1427 } | 1502 } |
1428 } | 1503 } |
1429 } else { | 1504 } else { |
1430 defaultRuleSet = getDefaultRuleSet(); | 1505 defaultRuleSet = getDefaultRuleSet(); |
1431 } | 1506 } |
| 1507 originalDescription = rules; |
| 1508 } |
| 1509 |
| 1510 // override the NumberFormat implementation in order to |
| 1511 // lazily initialize relevant items |
| 1512 void |
| 1513 RuleBasedNumberFormat::setContext(UDisplayContext value, UErrorCode& status) |
| 1514 { |
| 1515 NumberFormat::setContext(value, status); |
| 1516 if (U_SUCCESS(status)) { |
| 1517 if (!capitalizationInfoSet && |
| 1518 (value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || value==UD
ISPCTX_CAPITALIZATION_FOR_STANDALONE)) { |
| 1519 initCapitalizationContextInfo(locale); |
| 1520 capitalizationInfoSet = TRUE; |
| 1521 } |
| 1522 #if !UCONFIG_NO_BREAK_ITERATION |
| 1523 if ( capitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FO
R_BEGINNING_OF_SENTENCE || |
| 1524 (value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitaliz
ationForUIListMenu) || |
| 1525 (value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalization
ForStandAlone)) ) { |
| 1526 UErrorCode status = U_ZERO_ERROR; |
| 1527 capitalizationBrkIter = BreakIterator::createSentenceInstance(locale
, status); |
| 1528 if (U_FAILURE(status)) { |
| 1529 delete capitalizationBrkIter; |
| 1530 capitalizationBrkIter = NULL; |
| 1531 } |
| 1532 } |
| 1533 #endif |
| 1534 } |
1432 } | 1535 } |
1433 | 1536 |
1434 void | 1537 void |
| 1538 RuleBasedNumberFormat::initCapitalizationContextInfo(const Locale& thelocale) |
| 1539 { |
| 1540 #if !UCONFIG_NO_BREAK_ITERATION |
| 1541 const char * localeID = (thelocale != NULL)? thelocale.getBaseName(): NULL; |
| 1542 UErrorCode status = U_ZERO_ERROR; |
| 1543 UResourceBundle *rb = ures_open(NULL, localeID, &status); |
| 1544 rb = ures_getByKeyWithFallback(rb, "contextTransforms", rb, &status); |
| 1545 rb = ures_getByKeyWithFallback(rb, "number-spellout", rb, &status); |
| 1546 if (U_SUCCESS(status) && rb != NULL) { |
| 1547 int32_t len = 0; |
| 1548 const int32_t * intVector = ures_getIntVector(rb, &len, &status); |
| 1549 if (U_SUCCESS(status) && intVector != NULL && len >= 2) { |
| 1550 capitalizationForUIListMenu = intVector[0]; |
| 1551 capitalizationForStandAlone = intVector[1]; |
| 1552 } |
| 1553 } |
| 1554 ures_close(rb); |
| 1555 #endif |
| 1556 } |
| 1557 |
| 1558 void |
1435 RuleBasedNumberFormat::stripWhitespace(UnicodeString& description) | 1559 RuleBasedNumberFormat::stripWhitespace(UnicodeString& description) |
1436 { | 1560 { |
1437 // iterate through the characters... | 1561 // iterate through the characters... |
1438 UnicodeString result; | 1562 UnicodeString result; |
1439 | 1563 |
1440 int start = 0; | 1564 int start = 0; |
1441 while (start != -1 && start < description.length()) { | 1565 while (start != -1 && start < description.length()) { |
1442 // seek to the first non-whitespace character... | 1566 // seek to the first non-whitespace character... |
1443 while (start < description.length() | 1567 while (start < description.length() |
1444 && PatternProps::isWhiteSpace(description.charAt(start))) { | 1568 && PatternProps::isWhiteSpace(description.charAt(start))) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1491 delete collator; | 1615 delete collator; |
1492 #endif | 1616 #endif |
1493 collator = NULL; | 1617 collator = NULL; |
1494 | 1618 |
1495 delete decimalFormatSymbols; | 1619 delete decimalFormatSymbols; |
1496 decimalFormatSymbols = NULL; | 1620 decimalFormatSymbols = NULL; |
1497 | 1621 |
1498 delete lenientParseRules; | 1622 delete lenientParseRules; |
1499 lenientParseRules = NULL; | 1623 lenientParseRules = NULL; |
1500 | 1624 |
| 1625 #if !UCONFIG_NO_BREAK_ITERATION |
| 1626 delete capitalizationBrkIter; |
| 1627 capitalizationBrkIter = NULL; |
| 1628 #endif |
| 1629 |
1501 if (localizations) localizations = localizations->unref(); | 1630 if (localizations) localizations = localizations->unref(); |
1502 } | 1631 } |
1503 | 1632 |
1504 | 1633 |
1505 //----------------------------------------------------------------------- | 1634 //----------------------------------------------------------------------- |
1506 // package-internal API | 1635 // package-internal API |
1507 //----------------------------------------------------------------------- | 1636 //----------------------------------------------------------------------- |
1508 | 1637 |
1509 /** | 1638 /** |
1510 * Returns the collator to use for lenient parsing. The collator is lazily crea
ted: | 1639 * Returns the collator to use for lenient parsing. The collator is lazily crea
ted: |
1511 * this function creates it the first time it's called. | 1640 * this function creates it the first time it's called. |
1512 * @return The collator to use for lenient parsing, or null if lenient parsing | 1641 * @return The collator to use for lenient parsing, or null if lenient parsing |
1513 * is turned off. | 1642 * is turned off. |
1514 */ | 1643 */ |
1515 Collator* | 1644 const RuleBasedCollator* |
1516 RuleBasedNumberFormat::getCollator() const | 1645 RuleBasedNumberFormat::getCollator() const |
1517 { | 1646 { |
1518 #if !UCONFIG_NO_COLLATION | 1647 #if !UCONFIG_NO_COLLATION |
1519 if (!ruleSets) { | 1648 if (!ruleSets) { |
1520 return NULL; | 1649 return NULL; |
1521 } | 1650 } |
1522 | 1651 |
1523 // lazy-evaulate the collator | 1652 // lazy-evaluate the collator |
1524 if (collator == NULL && lenient) { | 1653 if (collator == NULL && lenient) { |
1525 // create a default collator based on the formatter's locale, | 1654 // create a default collator based on the formatter's locale, |
1526 // then pull out that collator's rules, append any additional | 1655 // then pull out that collator's rules, append any additional |
1527 // rules specified in the description, and create a _new_ | 1656 // rules specified in the description, and create a _new_ |
1528 // collator based on the combinaiton of those rules | 1657 // collator based on the combinaiton of those rules |
1529 | 1658 |
1530 UErrorCode status = U_ZERO_ERROR; | 1659 UErrorCode status = U_ZERO_ERROR; |
1531 | 1660 |
1532 Collator* temp = Collator::createInstance(locale, status); | 1661 Collator* temp = Collator::createInstance(locale, status); |
1533 RuleBasedCollator* newCollator; | 1662 RuleBasedCollator* newCollator; |
1534 if (U_SUCCESS(status) && (newCollator = dynamic_cast<RuleBasedCollator*>
(temp)) != NULL) { | 1663 if (U_SUCCESS(status) && (newCollator = dynamic_cast<RuleBasedCollator*>
(temp)) != NULL) { |
1535 if (lenientParseRules) { | 1664 if (lenientParseRules) { |
1536 UnicodeString rules(newCollator->getRules()); | 1665 UnicodeString rules(newCollator->getRules()); |
1537 rules.append(*lenientParseRules); | 1666 rules.append(*lenientParseRules); |
1538 | 1667 |
1539 newCollator = new RuleBasedCollator(rules, status); | 1668 newCollator = new RuleBasedCollator(rules, status); |
1540 // Exit if newCollator could not be created. | 1669 // Exit if newCollator could not be created. |
1541 if (newCollator == NULL) { | 1670 if (newCollator == NULL) { |
1542 » return NULL; | 1671 return NULL; |
1543 } | 1672 } |
1544 } else { | 1673 } else { |
1545 temp = NULL; | 1674 temp = NULL; |
1546 } | 1675 } |
1547 if (U_SUCCESS(status)) { | 1676 if (U_SUCCESS(status)) { |
1548 newCollator->setAttribute(UCOL_DECOMPOSITION_MODE, UCOL_ON, stat
us); | 1677 newCollator->setAttribute(UCOL_DECOMPOSITION_MODE, UCOL_ON, stat
us); |
1549 // cast away const | 1678 // cast away const |
1550 ((RuleBasedNumberFormat*)this)->collator = newCollator; | 1679 ((RuleBasedNumberFormat*)this)->collator = newCollator; |
1551 } else { | 1680 } else { |
1552 delete newCollator; | 1681 delete newCollator; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1611 } | 1740 } |
1612 } | 1741 } |
1613 | 1742 |
1614 // Setting the symbols is equlivalent to adopting a newly created localized symb
ols. | 1743 // Setting the symbols is equlivalent to adopting a newly created localized symb
ols. |
1615 void | 1744 void |
1616 RuleBasedNumberFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbo
ls) | 1745 RuleBasedNumberFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbo
ls) |
1617 { | 1746 { |
1618 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols)); | 1747 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols)); |
1619 } | 1748 } |
1620 | 1749 |
| 1750 PluralFormat * |
| 1751 RuleBasedNumberFormat::createPluralFormat(UPluralType pluralType, |
| 1752 const UnicodeString &pattern, |
| 1753 UErrorCode& status) const |
| 1754 { |
| 1755 return new PluralFormat(locale, pluralType, pattern, status); |
| 1756 } |
| 1757 |
1621 U_NAMESPACE_END | 1758 U_NAMESPACE_END |
1622 | 1759 |
1623 /* U_HAVE_RBNF */ | 1760 /* U_HAVE_RBNF */ |
1624 #endif | 1761 #endif |
OLD | NEW |