xref: /aosp_15_r20/external/icu/libicu/cts_headers/plurrule_impl.h (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1*0e209d39SAndroid Build Coastguard Worker // © 2016 and later: Unicode, Inc. and others.
2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html
3*0e209d39SAndroid Build Coastguard Worker /*
4*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
5*0e209d39SAndroid Build Coastguard Worker * Copyright (C) 2007-2016, International Business Machines Corporation and
6*0e209d39SAndroid Build Coastguard Worker * others. All Rights Reserved.
7*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
8*0e209d39SAndroid Build Coastguard Worker *
9*0e209d39SAndroid Build Coastguard Worker * File PLURRULE_IMPL.H
10*0e209d39SAndroid Build Coastguard Worker *
11*0e209d39SAndroid Build Coastguard Worker *******************************************************************************
12*0e209d39SAndroid Build Coastguard Worker */
13*0e209d39SAndroid Build Coastguard Worker 
14*0e209d39SAndroid Build Coastguard Worker 
15*0e209d39SAndroid Build Coastguard Worker #ifndef PLURRULE_IMPL
16*0e209d39SAndroid Build Coastguard Worker #define PLURRULE_IMPL
17*0e209d39SAndroid Build Coastguard Worker 
18*0e209d39SAndroid Build Coastguard Worker // Internal definitions for the PluralRules implementation.
19*0e209d39SAndroid Build Coastguard Worker 
20*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h"
21*0e209d39SAndroid Build Coastguard Worker 
22*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_FORMATTING
23*0e209d39SAndroid Build Coastguard Worker 
24*0e209d39SAndroid Build Coastguard Worker #include "unicode/format.h"
25*0e209d39SAndroid Build Coastguard Worker #include "unicode/locid.h"
26*0e209d39SAndroid Build Coastguard Worker #include "unicode/parseerr.h"
27*0e209d39SAndroid Build Coastguard Worker #include "unicode/strenum.h"
28*0e209d39SAndroid Build Coastguard Worker #include "unicode/ures.h"
29*0e209d39SAndroid Build Coastguard Worker #include "uvector.h"
30*0e209d39SAndroid Build Coastguard Worker #include "hash.h"
31*0e209d39SAndroid Build Coastguard Worker #include "uassert.h"
32*0e209d39SAndroid Build Coastguard Worker 
33*0e209d39SAndroid Build Coastguard Worker /**
34*0e209d39SAndroid Build Coastguard Worker  * A FixedDecimal version of UPLRULES_NO_UNIQUE_VALUE used in PluralRulesTest
35*0e209d39SAndroid Build Coastguard Worker  * for parsing of samples.
36*0e209d39SAndroid Build Coastguard Worker  */
37*0e209d39SAndroid Build Coastguard Worker #define UPLRULES_NO_UNIQUE_VALUE_DECIMAL(ERROR_CODE) (DecimalQuantity::fromExponentString(u"-0.00123456777", ERROR_CODE))
38*0e209d39SAndroid Build Coastguard Worker 
39*0e209d39SAndroid Build Coastguard Worker class PluralRulesTest;
40*0e209d39SAndroid Build Coastguard Worker 
41*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN
42*0e209d39SAndroid Build Coastguard Worker 
43*0e209d39SAndroid Build Coastguard Worker class AndConstraint;
44*0e209d39SAndroid Build Coastguard Worker class RuleChain;
45*0e209d39SAndroid Build Coastguard Worker class DigitInterval;
46*0e209d39SAndroid Build Coastguard Worker class PluralRules;
47*0e209d39SAndroid Build Coastguard Worker class VisibleDigits;
48*0e209d39SAndroid Build Coastguard Worker 
49*0e209d39SAndroid Build Coastguard Worker namespace pluralimpl {
50*0e209d39SAndroid Build Coastguard Worker 
51*0e209d39SAndroid Build Coastguard Worker // TODO: Remove this and replace with u"" literals. Was for EBCDIC compatibility.
52*0e209d39SAndroid Build Coastguard Worker 
53*0e209d39SAndroid Build Coastguard Worker static const char16_t DOT = ((char16_t) 0x002E);
54*0e209d39SAndroid Build Coastguard Worker static const char16_t SINGLE_QUOTE = ((char16_t) 0x0027);
55*0e209d39SAndroid Build Coastguard Worker static const char16_t SLASH = ((char16_t) 0x002F);
56*0e209d39SAndroid Build Coastguard Worker static const char16_t BACKSLASH = ((char16_t) 0x005C);
57*0e209d39SAndroid Build Coastguard Worker static const char16_t SPACE = ((char16_t) 0x0020);
58*0e209d39SAndroid Build Coastguard Worker static const char16_t EXCLAMATION = ((char16_t) 0x0021);
59*0e209d39SAndroid Build Coastguard Worker static const char16_t QUOTATION_MARK = ((char16_t) 0x0022);
60*0e209d39SAndroid Build Coastguard Worker static const char16_t NUMBER_SIGN = ((char16_t) 0x0023);
61*0e209d39SAndroid Build Coastguard Worker static const char16_t PERCENT_SIGN = ((char16_t) 0x0025);
62*0e209d39SAndroid Build Coastguard Worker static const char16_t ASTERISK = ((char16_t) 0x002A);
63*0e209d39SAndroid Build Coastguard Worker static const char16_t COMMA = ((char16_t) 0x002C);
64*0e209d39SAndroid Build Coastguard Worker static const char16_t HYPHEN = ((char16_t) 0x002D);
65*0e209d39SAndroid Build Coastguard Worker static const char16_t U_ZERO = ((char16_t) 0x0030);
66*0e209d39SAndroid Build Coastguard Worker static const char16_t U_ONE = ((char16_t) 0x0031);
67*0e209d39SAndroid Build Coastguard Worker static const char16_t U_TWO = ((char16_t) 0x0032);
68*0e209d39SAndroid Build Coastguard Worker static const char16_t U_THREE = ((char16_t) 0x0033);
69*0e209d39SAndroid Build Coastguard Worker static const char16_t U_FOUR = ((char16_t) 0x0034);
70*0e209d39SAndroid Build Coastguard Worker static const char16_t U_FIVE = ((char16_t) 0x0035);
71*0e209d39SAndroid Build Coastguard Worker static const char16_t U_SIX = ((char16_t) 0x0036);
72*0e209d39SAndroid Build Coastguard Worker static const char16_t U_SEVEN = ((char16_t) 0x0037);
73*0e209d39SAndroid Build Coastguard Worker static const char16_t U_EIGHT = ((char16_t) 0x0038);
74*0e209d39SAndroid Build Coastguard Worker static const char16_t U_NINE = ((char16_t) 0x0039);
75*0e209d39SAndroid Build Coastguard Worker static const char16_t COLON = ((char16_t) 0x003A);
76*0e209d39SAndroid Build Coastguard Worker static const char16_t SEMI_COLON = ((char16_t) 0x003B);
77*0e209d39SAndroid Build Coastguard Worker static const char16_t EQUALS = ((char16_t) 0x003D);
78*0e209d39SAndroid Build Coastguard Worker static const char16_t AT = ((char16_t) 0x0040);
79*0e209d39SAndroid Build Coastguard Worker static const char16_t CAP_A = ((char16_t) 0x0041);
80*0e209d39SAndroid Build Coastguard Worker static const char16_t CAP_B = ((char16_t) 0x0042);
81*0e209d39SAndroid Build Coastguard Worker static const char16_t CAP_R = ((char16_t) 0x0052);
82*0e209d39SAndroid Build Coastguard Worker static const char16_t CAP_Z = ((char16_t) 0x005A);
83*0e209d39SAndroid Build Coastguard Worker static const char16_t LOWLINE = ((char16_t) 0x005F);
84*0e209d39SAndroid Build Coastguard Worker static const char16_t LEFTBRACE = ((char16_t) 0x007B);
85*0e209d39SAndroid Build Coastguard Worker static const char16_t RIGHTBRACE = ((char16_t) 0x007D);
86*0e209d39SAndroid Build Coastguard Worker static const char16_t TILDE = ((char16_t) 0x007E);
87*0e209d39SAndroid Build Coastguard Worker static const char16_t ELLIPSIS = ((char16_t) 0x2026);
88*0e209d39SAndroid Build Coastguard Worker 
89*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_A = ((char16_t) 0x0061);
90*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_B = ((char16_t) 0x0062);
91*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_C = ((char16_t) 0x0063);
92*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_D = ((char16_t) 0x0064);
93*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_E = ((char16_t) 0x0065);
94*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_F = ((char16_t) 0x0066);
95*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_G = ((char16_t) 0x0067);
96*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_H = ((char16_t) 0x0068);
97*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_I = ((char16_t) 0x0069);
98*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_J = ((char16_t) 0x006a);
99*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_K = ((char16_t) 0x006B);
100*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_L = ((char16_t) 0x006C);
101*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_M = ((char16_t) 0x006D);
102*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_N = ((char16_t) 0x006E);
103*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_O = ((char16_t) 0x006F);
104*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_P = ((char16_t) 0x0070);
105*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_Q = ((char16_t) 0x0071);
106*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_R = ((char16_t) 0x0072);
107*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_S = ((char16_t) 0x0073);
108*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_T = ((char16_t) 0x0074);
109*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_U = ((char16_t) 0x0075);
110*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_V = ((char16_t) 0x0076);
111*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_W = ((char16_t) 0x0077);
112*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_Y = ((char16_t) 0x0079);
113*0e209d39SAndroid Build Coastguard Worker static const char16_t LOW_Z = ((char16_t) 0x007A);
114*0e209d39SAndroid Build Coastguard Worker 
115*0e209d39SAndroid Build Coastguard Worker }
116*0e209d39SAndroid Build Coastguard Worker 
117*0e209d39SAndroid Build Coastguard Worker 
118*0e209d39SAndroid Build Coastguard Worker static const int32_t PLURAL_RANGE_HIGH = 0x7fffffff;
119*0e209d39SAndroid Build Coastguard Worker 
120*0e209d39SAndroid Build Coastguard Worker enum tokenType {
121*0e209d39SAndroid Build Coastguard Worker   none,
122*0e209d39SAndroid Build Coastguard Worker   tNumber,
123*0e209d39SAndroid Build Coastguard Worker   tComma,
124*0e209d39SAndroid Build Coastguard Worker   tSemiColon,
125*0e209d39SAndroid Build Coastguard Worker   tSpace,
126*0e209d39SAndroid Build Coastguard Worker   tColon,
127*0e209d39SAndroid Build Coastguard Worker   tAt,           // '@'
128*0e209d39SAndroid Build Coastguard Worker   tDot,
129*0e209d39SAndroid Build Coastguard Worker   tDot2,
130*0e209d39SAndroid Build Coastguard Worker   tEllipsis,
131*0e209d39SAndroid Build Coastguard Worker   tKeyword,
132*0e209d39SAndroid Build Coastguard Worker   tAnd,
133*0e209d39SAndroid Build Coastguard Worker   tOr,
134*0e209d39SAndroid Build Coastguard Worker   tMod,          // 'mod' or '%'
135*0e209d39SAndroid Build Coastguard Worker   tNot,          //  'not' only.
136*0e209d39SAndroid Build Coastguard Worker   tIn,           //  'in'  only.
137*0e209d39SAndroid Build Coastguard Worker   tEqual,        //  '='   only.
138*0e209d39SAndroid Build Coastguard Worker   tNotEqual,     //  '!='
139*0e209d39SAndroid Build Coastguard Worker   tTilde,
140*0e209d39SAndroid Build Coastguard Worker   tWithin,
141*0e209d39SAndroid Build Coastguard Worker   tIs,
142*0e209d39SAndroid Build Coastguard Worker   tVariableN,
143*0e209d39SAndroid Build Coastguard Worker   tVariableI,
144*0e209d39SAndroid Build Coastguard Worker   tVariableF,
145*0e209d39SAndroid Build Coastguard Worker   tVariableV,
146*0e209d39SAndroid Build Coastguard Worker   tVariableT,
147*0e209d39SAndroid Build Coastguard Worker   tVariableE,
148*0e209d39SAndroid Build Coastguard Worker   tVariableC,
149*0e209d39SAndroid Build Coastguard Worker   tDecimal,
150*0e209d39SAndroid Build Coastguard Worker   tInteger,
151*0e209d39SAndroid Build Coastguard Worker   tEOF
152*0e209d39SAndroid Build Coastguard Worker };
153*0e209d39SAndroid Build Coastguard Worker 
154*0e209d39SAndroid Build Coastguard Worker 
155*0e209d39SAndroid Build Coastguard Worker class PluralRuleParser: public UMemory {
156*0e209d39SAndroid Build Coastguard Worker public:
157*0e209d39SAndroid Build Coastguard Worker     PluralRuleParser();
158*0e209d39SAndroid Build Coastguard Worker     virtual ~PluralRuleParser();
159*0e209d39SAndroid Build Coastguard Worker 
160*0e209d39SAndroid Build Coastguard Worker     void parse(const UnicodeString &rules, PluralRules *dest, UErrorCode &status);
161*0e209d39SAndroid Build Coastguard Worker     void getNextToken(UErrorCode &status);
162*0e209d39SAndroid Build Coastguard Worker     void checkSyntax(UErrorCode &status);
163*0e209d39SAndroid Build Coastguard Worker     static int32_t getNumberValue(const UnicodeString &token);
164*0e209d39SAndroid Build Coastguard Worker 
165*0e209d39SAndroid Build Coastguard Worker private:
166*0e209d39SAndroid Build Coastguard Worker     static tokenType getKeyType(const UnicodeString& token, tokenType type);
167*0e209d39SAndroid Build Coastguard Worker     static tokenType charType(char16_t ch);
168*0e209d39SAndroid Build Coastguard Worker     static UBool isValidKeyword(const UnicodeString& token);
169*0e209d39SAndroid Build Coastguard Worker 
170*0e209d39SAndroid Build Coastguard Worker     const UnicodeString  *ruleSrc;  // The rules string.
171*0e209d39SAndroid Build Coastguard Worker     int32_t        ruleIndex;       // String index in the input rules, the current parse position.
172*0e209d39SAndroid Build Coastguard Worker     UnicodeString  token;           // Token most recently scanned.
173*0e209d39SAndroid Build Coastguard Worker     tokenType      type;
174*0e209d39SAndroid Build Coastguard Worker     tokenType      prevType;
175*0e209d39SAndroid Build Coastguard Worker 
176*0e209d39SAndroid Build Coastguard Worker                                     // The items currently being parsed & built.
177*0e209d39SAndroid Build Coastguard Worker                                     // Note: currentChain may not be the last RuleChain in the
178*0e209d39SAndroid Build Coastguard Worker                                     //       list because the "other" chain is forced to the end.
179*0e209d39SAndroid Build Coastguard Worker     AndConstraint *curAndConstraint;
180*0e209d39SAndroid Build Coastguard Worker     RuleChain     *currentChain;
181*0e209d39SAndroid Build Coastguard Worker 
182*0e209d39SAndroid Build Coastguard Worker     int32_t        rangeLowIdx;     // Indices in the UVector of ranges of the
183*0e209d39SAndroid Build Coastguard Worker     int32_t        rangeHiIdx;      //    low and hi values currently being parsed.
184*0e209d39SAndroid Build Coastguard Worker 
185*0e209d39SAndroid Build Coastguard Worker     enum EParseState {
186*0e209d39SAndroid Build Coastguard Worker        kKeyword,
187*0e209d39SAndroid Build Coastguard Worker        kExpr,
188*0e209d39SAndroid Build Coastguard Worker        kValue,
189*0e209d39SAndroid Build Coastguard Worker        kRangeList,
190*0e209d39SAndroid Build Coastguard Worker        kSamples
191*0e209d39SAndroid Build Coastguard Worker     };
192*0e209d39SAndroid Build Coastguard Worker };
193*0e209d39SAndroid Build Coastguard Worker 
194*0e209d39SAndroid Build Coastguard Worker enum PluralOperand {
195*0e209d39SAndroid Build Coastguard Worker     /**
196*0e209d39SAndroid Build Coastguard Worker     * The double value of the entire number.
197*0e209d39SAndroid Build Coastguard Worker     */
198*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_N,
199*0e209d39SAndroid Build Coastguard Worker 
200*0e209d39SAndroid Build Coastguard Worker     /**
201*0e209d39SAndroid Build Coastguard Worker      * The integer value, with the fraction digits truncated off.
202*0e209d39SAndroid Build Coastguard Worker      */
203*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_I,
204*0e209d39SAndroid Build Coastguard Worker 
205*0e209d39SAndroid Build Coastguard Worker     /**
206*0e209d39SAndroid Build Coastguard Worker      * All visible fraction digits as an integer, including trailing zeros.
207*0e209d39SAndroid Build Coastguard Worker      */
208*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_F,
209*0e209d39SAndroid Build Coastguard Worker 
210*0e209d39SAndroid Build Coastguard Worker     /**
211*0e209d39SAndroid Build Coastguard Worker      * Visible fraction digits as an integer, not including trailing zeros.
212*0e209d39SAndroid Build Coastguard Worker      */
213*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_T,
214*0e209d39SAndroid Build Coastguard Worker 
215*0e209d39SAndroid Build Coastguard Worker     /**
216*0e209d39SAndroid Build Coastguard Worker      * Number of visible fraction digits.
217*0e209d39SAndroid Build Coastguard Worker      */
218*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_V,
219*0e209d39SAndroid Build Coastguard Worker 
220*0e209d39SAndroid Build Coastguard Worker     /**
221*0e209d39SAndroid Build Coastguard Worker      * Number of visible fraction digits, not including trailing zeros.
222*0e209d39SAndroid Build Coastguard Worker      */
223*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_W,
224*0e209d39SAndroid Build Coastguard Worker 
225*0e209d39SAndroid Build Coastguard Worker     /**
226*0e209d39SAndroid Build Coastguard Worker      * Suppressed exponent for scientific notation (exponent needed in
227*0e209d39SAndroid Build Coastguard Worker      * scientific notation to approximate i).
228*0e209d39SAndroid Build Coastguard Worker      */
229*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_E,
230*0e209d39SAndroid Build Coastguard Worker 
231*0e209d39SAndroid Build Coastguard Worker     /**
232*0e209d39SAndroid Build Coastguard Worker      * This operand is currently treated as an alias for `PLURAL_OPERAND_E`.
233*0e209d39SAndroid Build Coastguard Worker      * In the future, it will represent:
234*0e209d39SAndroid Build Coastguard Worker      *
235*0e209d39SAndroid Build Coastguard Worker      * Suppressed exponent for compact notation (exponent needed in
236*0e209d39SAndroid Build Coastguard Worker      * compact notation to approximate i).
237*0e209d39SAndroid Build Coastguard Worker      */
238*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_C,
239*0e209d39SAndroid Build Coastguard Worker 
240*0e209d39SAndroid Build Coastguard Worker     /**
241*0e209d39SAndroid Build Coastguard Worker      * THIS OPERAND IS DEPRECATED AND HAS BEEN REMOVED FROM THE SPEC.
242*0e209d39SAndroid Build Coastguard Worker      *
243*0e209d39SAndroid Build Coastguard Worker      * <p>Returns the integer value, but will fail if the number has fraction digits.
244*0e209d39SAndroid Build Coastguard Worker      * That is, using "j" instead of "i" is like implicitly adding "v is 0".
245*0e209d39SAndroid Build Coastguard Worker      *
246*0e209d39SAndroid Build Coastguard Worker      * <p>For example, "j is 3" is equivalent to "i is 3 and v is 0": it matches
247*0e209d39SAndroid Build Coastguard Worker      * "3" but not "3.1" or "3.0".
248*0e209d39SAndroid Build Coastguard Worker      */
249*0e209d39SAndroid Build Coastguard Worker     PLURAL_OPERAND_J
250*0e209d39SAndroid Build Coastguard Worker };
251*0e209d39SAndroid Build Coastguard Worker 
252*0e209d39SAndroid Build Coastguard Worker /**
253*0e209d39SAndroid Build Coastguard Worker  * Converts from the tokenType enum to PluralOperand. Asserts that the given
254*0e209d39SAndroid Build Coastguard Worker  * tokenType can be mapped to a PluralOperand.
255*0e209d39SAndroid Build Coastguard Worker  */
256*0e209d39SAndroid Build Coastguard Worker PluralOperand tokenTypeToPluralOperand(tokenType tt);
257*0e209d39SAndroid Build Coastguard Worker 
258*0e209d39SAndroid Build Coastguard Worker /**
259*0e209d39SAndroid Build Coastguard Worker  * An interface to FixedDecimal, allowing for other implementations.
260*0e209d39SAndroid Build Coastguard Worker  * @internal
261*0e209d39SAndroid Build Coastguard Worker  */
262*0e209d39SAndroid Build Coastguard Worker class U_I18N_API IFixedDecimal {
263*0e209d39SAndroid Build Coastguard Worker   public:
264*0e209d39SAndroid Build Coastguard Worker     virtual ~IFixedDecimal();
265*0e209d39SAndroid Build Coastguard Worker 
266*0e209d39SAndroid Build Coastguard Worker     /**
267*0e209d39SAndroid Build Coastguard Worker      * Returns the value corresponding to the specified operand (n, i, f, t, v, or w).
268*0e209d39SAndroid Build Coastguard Worker      * If the operand is 'n', returns a double; otherwise, returns an integer.
269*0e209d39SAndroid Build Coastguard Worker      */
270*0e209d39SAndroid Build Coastguard Worker     virtual double getPluralOperand(PluralOperand operand) const = 0;
271*0e209d39SAndroid Build Coastguard Worker 
272*0e209d39SAndroid Build Coastguard Worker     virtual bool isNaN() const = 0;
273*0e209d39SAndroid Build Coastguard Worker 
274*0e209d39SAndroid Build Coastguard Worker     virtual bool isInfinite() const = 0;
275*0e209d39SAndroid Build Coastguard Worker 
276*0e209d39SAndroid Build Coastguard Worker     /** Whether the number has no nonzero fraction digits. */
277*0e209d39SAndroid Build Coastguard Worker     virtual bool hasIntegerValue() const = 0;
278*0e209d39SAndroid Build Coastguard Worker };
279*0e209d39SAndroid Build Coastguard Worker 
280*0e209d39SAndroid Build Coastguard Worker /**
281*0e209d39SAndroid Build Coastguard Worker  * class FixedDecimal serves to communicate the properties
282*0e209d39SAndroid Build Coastguard Worker  * of a formatted number from a decimal formatter to PluralRules::select()
283*0e209d39SAndroid Build Coastguard Worker  *
284*0e209d39SAndroid Build Coastguard Worker  * see DecimalFormat::getFixedDecimal()
285*0e209d39SAndroid Build Coastguard Worker  * @internal
286*0e209d39SAndroid Build Coastguard Worker  */
287*0e209d39SAndroid Build Coastguard Worker class U_I18N_API FixedDecimal: public IFixedDecimal, public UObject {
288*0e209d39SAndroid Build Coastguard Worker   public:
289*0e209d39SAndroid Build Coastguard Worker     /**
290*0e209d39SAndroid Build Coastguard Worker       * @param n   the number, e.g. 12.345
291*0e209d39SAndroid Build Coastguard Worker       * @param v   The number of visible fraction digits, e.g. 3
292*0e209d39SAndroid Build Coastguard Worker       * @param f   The fraction digits, e.g. 345
293*0e209d39SAndroid Build Coastguard Worker       * @param e   The exponent, e.g. 7 in 1.2e7, for scientific notation
294*0e209d39SAndroid Build Coastguard Worker       * @param c   Currently: an alias for param `e`.
295*0e209d39SAndroid Build Coastguard Worker       */
296*0e209d39SAndroid Build Coastguard Worker     FixedDecimal(double  n, int32_t v, int64_t f, int32_t e, int32_t c);
297*0e209d39SAndroid Build Coastguard Worker     FixedDecimal(double  n, int32_t v, int64_t f, int32_t e);
298*0e209d39SAndroid Build Coastguard Worker     FixedDecimal(double  n, int32_t v, int64_t f);
299*0e209d39SAndroid Build Coastguard Worker     FixedDecimal(double n, int32_t);
300*0e209d39SAndroid Build Coastguard Worker     explicit FixedDecimal(double n);
301*0e209d39SAndroid Build Coastguard Worker     FixedDecimal();
302*0e209d39SAndroid Build Coastguard Worker     ~FixedDecimal() override;
303*0e209d39SAndroid Build Coastguard Worker     FixedDecimal(const UnicodeString &s, UErrorCode &ec);
304*0e209d39SAndroid Build Coastguard Worker     FixedDecimal(const FixedDecimal &other);
305*0e209d39SAndroid Build Coastguard Worker 
306*0e209d39SAndroid Build Coastguard Worker     static FixedDecimal createWithExponent(double n, int32_t v, int32_t e);
307*0e209d39SAndroid Build Coastguard Worker 
308*0e209d39SAndroid Build Coastguard Worker     double getPluralOperand(PluralOperand operand) const override;
309*0e209d39SAndroid Build Coastguard Worker     bool isNaN() const override;
310*0e209d39SAndroid Build Coastguard Worker     bool isInfinite() const override;
311*0e209d39SAndroid Build Coastguard Worker     bool hasIntegerValue() const override;
312*0e209d39SAndroid Build Coastguard Worker 
313*0e209d39SAndroid Build Coastguard Worker     bool isNanOrInfinity() const;  // used in decimfmtimpl.cpp
314*0e209d39SAndroid Build Coastguard Worker 
315*0e209d39SAndroid Build Coastguard Worker     int32_t getVisibleFractionDigitCount() const;
316*0e209d39SAndroid Build Coastguard Worker 
317*0e209d39SAndroid Build Coastguard Worker     void init(double n, int32_t v, int64_t f, int32_t e, int32_t c);
318*0e209d39SAndroid Build Coastguard Worker     void init(double n, int32_t v, int64_t f, int32_t e);
319*0e209d39SAndroid Build Coastguard Worker     void init(double n, int32_t v, int64_t f);
320*0e209d39SAndroid Build Coastguard Worker     void init(double n);
321*0e209d39SAndroid Build Coastguard Worker     UBool quickInit(double n);  // Try a fast-path only initialization,
322*0e209d39SAndroid Build Coastguard Worker                                 //    return true if successful.
323*0e209d39SAndroid Build Coastguard Worker     void adjustForMinFractionDigits(int32_t min);
324*0e209d39SAndroid Build Coastguard Worker     static int64_t getFractionalDigits(double n, int32_t v);
325*0e209d39SAndroid Build Coastguard Worker     static int32_t decimals(double n);
326*0e209d39SAndroid Build Coastguard Worker 
327*0e209d39SAndroid Build Coastguard Worker     FixedDecimal& operator=(const FixedDecimal& other) = default;
328*0e209d39SAndroid Build Coastguard Worker     bool operator==(const FixedDecimal &other) const;
329*0e209d39SAndroid Build Coastguard Worker 
330*0e209d39SAndroid Build Coastguard Worker     UnicodeString toString() const;
331*0e209d39SAndroid Build Coastguard Worker 
332*0e209d39SAndroid Build Coastguard Worker     double doubleValue() const;
333*0e209d39SAndroid Build Coastguard Worker     int64_t longValue() const;
334*0e209d39SAndroid Build Coastguard Worker 
335*0e209d39SAndroid Build Coastguard Worker     double      source;
336*0e209d39SAndroid Build Coastguard Worker     int32_t     visibleDecimalDigitCount;
337*0e209d39SAndroid Build Coastguard Worker     int64_t     decimalDigits;
338*0e209d39SAndroid Build Coastguard Worker     int64_t     decimalDigitsWithoutTrailingZeros;
339*0e209d39SAndroid Build Coastguard Worker     int64_t     intValue;
340*0e209d39SAndroid Build Coastguard Worker     int32_t     exponent;
341*0e209d39SAndroid Build Coastguard Worker     UBool       _hasIntegerValue;
342*0e209d39SAndroid Build Coastguard Worker     UBool       isNegative;
343*0e209d39SAndroid Build Coastguard Worker     UBool       _isNaN;
344*0e209d39SAndroid Build Coastguard Worker     UBool       _isInfinite;
345*0e209d39SAndroid Build Coastguard Worker };
346*0e209d39SAndroid Build Coastguard Worker 
347*0e209d39SAndroid Build Coastguard Worker class AndConstraint : public UMemory  {
348*0e209d39SAndroid Build Coastguard Worker public:
349*0e209d39SAndroid Build Coastguard Worker     typedef enum RuleOp {
350*0e209d39SAndroid Build Coastguard Worker         NONE,
351*0e209d39SAndroid Build Coastguard Worker         MOD
352*0e209d39SAndroid Build Coastguard Worker     } RuleOp;
353*0e209d39SAndroid Build Coastguard Worker     RuleOp op = AndConstraint::NONE;
354*0e209d39SAndroid Build Coastguard Worker     int32_t opNum = -1;             // for mod expressions, the right operand of the mod.
355*0e209d39SAndroid Build Coastguard Worker     int32_t value = -1;             // valid for 'is' rules only.
356*0e209d39SAndroid Build Coastguard Worker     UVector32 *rangeList = nullptr; // for 'in', 'within' rules. Null otherwise.
357*0e209d39SAndroid Build Coastguard Worker     UBool negated = false;          // true for negated rules.
358*0e209d39SAndroid Build Coastguard Worker     UBool integerOnly = false;      // true for 'within' rules.
359*0e209d39SAndroid Build Coastguard Worker     tokenType digitsType = none;    // n | i | v | f constraint.
360*0e209d39SAndroid Build Coastguard Worker     AndConstraint *next = nullptr;
361*0e209d39SAndroid Build Coastguard Worker     // Internal error status, used for errors that occur during the copy constructor.
362*0e209d39SAndroid Build Coastguard Worker     UErrorCode fInternalStatus = U_ZERO_ERROR;
363*0e209d39SAndroid Build Coastguard Worker 
364*0e209d39SAndroid Build Coastguard Worker     AndConstraint() = default;
365*0e209d39SAndroid Build Coastguard Worker     AndConstraint(const AndConstraint& other);
366*0e209d39SAndroid Build Coastguard Worker     virtual ~AndConstraint();
367*0e209d39SAndroid Build Coastguard Worker     AndConstraint* add(UErrorCode& status);
368*0e209d39SAndroid Build Coastguard Worker     // UBool isFulfilled(double number);
369*0e209d39SAndroid Build Coastguard Worker     UBool isFulfilled(const IFixedDecimal &number);
370*0e209d39SAndroid Build Coastguard Worker };
371*0e209d39SAndroid Build Coastguard Worker 
372*0e209d39SAndroid Build Coastguard Worker class OrConstraint : public UMemory  {
373*0e209d39SAndroid Build Coastguard Worker public:
374*0e209d39SAndroid Build Coastguard Worker     AndConstraint *childNode = nullptr;
375*0e209d39SAndroid Build Coastguard Worker     OrConstraint *next = nullptr;
376*0e209d39SAndroid Build Coastguard Worker     // Internal error status, used for errors that occur during the copy constructor.
377*0e209d39SAndroid Build Coastguard Worker     UErrorCode fInternalStatus = U_ZERO_ERROR;
378*0e209d39SAndroid Build Coastguard Worker 
379*0e209d39SAndroid Build Coastguard Worker     OrConstraint() = default;
380*0e209d39SAndroid Build Coastguard Worker     OrConstraint(const OrConstraint& other);
381*0e209d39SAndroid Build Coastguard Worker     virtual ~OrConstraint();
382*0e209d39SAndroid Build Coastguard Worker     AndConstraint* add(UErrorCode& status);
383*0e209d39SAndroid Build Coastguard Worker     // UBool isFulfilled(double number);
384*0e209d39SAndroid Build Coastguard Worker     UBool isFulfilled(const IFixedDecimal &number);
385*0e209d39SAndroid Build Coastguard Worker };
386*0e209d39SAndroid Build Coastguard Worker 
387*0e209d39SAndroid Build Coastguard Worker class RuleChain : public UMemory  {
388*0e209d39SAndroid Build Coastguard Worker public:
389*0e209d39SAndroid Build Coastguard Worker     UnicodeString   fKeyword;
390*0e209d39SAndroid Build Coastguard Worker     RuleChain      *fNext = nullptr;
391*0e209d39SAndroid Build Coastguard Worker     OrConstraint   *ruleHeader = nullptr;
392*0e209d39SAndroid Build Coastguard Worker     UnicodeString   fDecimalSamples;  // Samples strings from rule source
393*0e209d39SAndroid Build Coastguard Worker     UnicodeString   fIntegerSamples;  //   without @decimal or @integer, otherwise unprocessed.
394*0e209d39SAndroid Build Coastguard Worker     UBool           fDecimalSamplesUnbounded = false;
395*0e209d39SAndroid Build Coastguard Worker     UBool           fIntegerSamplesUnbounded = false;
396*0e209d39SAndroid Build Coastguard Worker     // Internal error status, used for errors that occur during the copy constructor.
397*0e209d39SAndroid Build Coastguard Worker     UErrorCode      fInternalStatus = U_ZERO_ERROR;
398*0e209d39SAndroid Build Coastguard Worker 
399*0e209d39SAndroid Build Coastguard Worker     RuleChain() = default;
400*0e209d39SAndroid Build Coastguard Worker     RuleChain(const RuleChain& other);
401*0e209d39SAndroid Build Coastguard Worker     virtual ~RuleChain();
402*0e209d39SAndroid Build Coastguard Worker 
403*0e209d39SAndroid Build Coastguard Worker     UnicodeString select(const IFixedDecimal &number) const;
404*0e209d39SAndroid Build Coastguard Worker     void          dumpRules(UnicodeString& result);
405*0e209d39SAndroid Build Coastguard Worker     UErrorCode    getKeywords(int32_t maxArraySize, UnicodeString *keywords, int32_t& arraySize) const;
406*0e209d39SAndroid Build Coastguard Worker     UBool         isKeyword(const UnicodeString& keyword) const;
407*0e209d39SAndroid Build Coastguard Worker };
408*0e209d39SAndroid Build Coastguard Worker 
409*0e209d39SAndroid Build Coastguard Worker class PluralKeywordEnumeration : public StringEnumeration {
410*0e209d39SAndroid Build Coastguard Worker public:
411*0e209d39SAndroid Build Coastguard Worker     PluralKeywordEnumeration(RuleChain *header, UErrorCode& status);
412*0e209d39SAndroid Build Coastguard Worker     virtual ~PluralKeywordEnumeration();
413*0e209d39SAndroid Build Coastguard Worker     static UClassID U_EXPORT2 getStaticClassID();
414*0e209d39SAndroid Build Coastguard Worker     virtual UClassID getDynamicClassID() const override;
415*0e209d39SAndroid Build Coastguard Worker     virtual const UnicodeString* snext(UErrorCode& status) override;
416*0e209d39SAndroid Build Coastguard Worker     virtual void reset(UErrorCode& status) override;
417*0e209d39SAndroid Build Coastguard Worker     virtual int32_t count(UErrorCode& status) const override;
418*0e209d39SAndroid Build Coastguard Worker private:
419*0e209d39SAndroid Build Coastguard Worker     int32_t         pos;
420*0e209d39SAndroid Build Coastguard Worker     UVector         fKeywordNames;
421*0e209d39SAndroid Build Coastguard Worker };
422*0e209d39SAndroid Build Coastguard Worker 
423*0e209d39SAndroid Build Coastguard Worker 
424*0e209d39SAndroid Build Coastguard Worker class U_I18N_API PluralAvailableLocalesEnumeration: public StringEnumeration {
425*0e209d39SAndroid Build Coastguard Worker   public:
426*0e209d39SAndroid Build Coastguard Worker     PluralAvailableLocalesEnumeration(UErrorCode &status);
427*0e209d39SAndroid Build Coastguard Worker     virtual ~PluralAvailableLocalesEnumeration();
428*0e209d39SAndroid Build Coastguard Worker     virtual const char* next(int32_t *resultLength, UErrorCode& status) override;
429*0e209d39SAndroid Build Coastguard Worker     virtual void reset(UErrorCode& status) override;
430*0e209d39SAndroid Build Coastguard Worker     virtual int32_t count(UErrorCode& status) const override;
431*0e209d39SAndroid Build Coastguard Worker   private:
432*0e209d39SAndroid Build Coastguard Worker     UErrorCode      fOpenStatus;
433*0e209d39SAndroid Build Coastguard Worker     UResourceBundle *fLocales = nullptr;
434*0e209d39SAndroid Build Coastguard Worker     UResourceBundle *fRes = nullptr;
435*0e209d39SAndroid Build Coastguard Worker };
436*0e209d39SAndroid Build Coastguard Worker 
437*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END
438*0e209d39SAndroid Build Coastguard Worker 
439*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_FORMATTING */
440*0e209d39SAndroid Build Coastguard Worker 
441*0e209d39SAndroid Build Coastguard Worker #endif // _PLURRULE_IMPL
442*0e209d39SAndroid Build Coastguard Worker //eof
443