1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4************************************************************************
5* Copyright (c) 2007-2010, International Business Machines
6* Corporation and others.  All Rights Reserved.
7************************************************************************
8*/
9#ifndef FLDSET_H_
10#define FLDSET_H_
11
12#include "unicode/utypes.h"
13
14#if !UCONFIG_NO_FORMATTING
15#include "unicode/calendar.h"
16#include "unicode/ucal.h"
17#include "unicode/udat.h"
18#include "udbgutil.h"
19#include "dbgutil.h"
20#include "unicode/unistr.h"
21
22#define U_FIELDS_SET_MAX  64
23
24/**
25 * This class represents a collection of integer values (fields), each designated by
26 * one of a particular set of enum values.  Each integer value (int32_t) is optional and
27 * may or may not be set.
28 *
29 * @internal ICU 3.8
30 */
31class FieldsSet {
32    protected:
33        /**
34         * subclass interface - construct the FieldsSet to reference one of the standard
35         * enumerations.
36         * @param whichEnum which enumaration value goes with this set. Will be used to calculate string
37         * values and also enum size.
38         * @see UDebugEnumType
39         */
40        FieldsSet(UDebugEnumType whichEnum);
41
42        /**
43         * subclass interface - construct the FieldsSet without using a standard enum type.
44         * @param fieldCount how many fields this object can hold.
45         */
46        FieldsSet(int32_t fieldsCount);
47
48    public:
49
50      /**
51       * Compare two sets. In typical test usage, 'this' is the resul of
52       * a tested operation, and 'other' is the predefined expected value.
53       *
54       * @param other the set to compare against.
55       * @param status will return U_ILLEGAL_ARGUMENT_ERROR if sets are not the same size
56       * @return a formatted string listing which fields are set in
57       *   this, with the comparison made agaainst those fields in other.
58       */
59      U_NAMESPACE_QUALIFIER UnicodeString diffFrom(const FieldsSet& other, UErrorCode &status) const;
60
61    public:
62      /**
63       * Fill-in fields from a specified string, such as "NAME1=VALUE1,NAME2=VALUE2", etc.
64       * @param str string to parse
65       * @param status status of parse
66       * @return the number of valid parsed fields on success, or a negative number on failure.
67       */
68      int32_t parseFrom(const U_NAMESPACE_QUALIFIER UnicodeString& str, UErrorCode& status) {
69          return parseFrom(str,NULL,status);
70      }
71
72      /**
73       * Fill-in fields from a specified string, such as "NAME1=VALUE1,NAME2=VALUE2", etc.
74       * @param inheritFrom if a field's value is given as 0-length, such as NAME1 in "NAME1=,NAME2=VALUE2",
75       * the specified FieldsSet's value for NAME1 will be copied into this.
76       * @param str string to parse
77       * @param status status of parse
78       * @return the number of valid parsed fields on success, or a negative number on failure.
79       */
80      int32_t parseFrom(const U_NAMESPACE_QUALIFIER UnicodeString& str,
81                        const FieldsSet& inheritFrom,
82                        UErrorCode& status) {
83          return parseFrom(str, &inheritFrom, status);
84      }
85
86      /**
87       * Fill-in fields from a specified string, such as "NAME1=VALUE1,NAME2=VALUE2", etc.
88       * @param inheritFrom if a field's value is given as 0-length, such as NAME1 in "NAME1=,NAME2=VALUE2",
89       * the specified FieldsSet's value for NAME1 will be copied into this.
90       * @param str string to parse
91       * @param status status of parse
92       * @return the number of valid parsed fields on success, or a negative number on failure.
93       */
94      int32_t parseFrom(const U_NAMESPACE_QUALIFIER UnicodeString& str,
95                        const FieldsSet* inheritFrom,
96                        UErrorCode& status);
97
98    protected:
99      /**
100       * Callback interface for subclass.
101       * This function is called when parsing a field name, such as "MONTH"  in "MONTH=4".
102       * Base implementation is to lookup the enum value using udbg_* utilities, or else as an integer if
103       * enum is not available.
104       *
105       * If there is a special directive, the implementer can catch it here and return -1 after special processing completes.
106       *
107       * @param inheritFrom the set inheriting from - may be null.
108       * @param name the field name (key side)
109       * @param substr the string in question (value side)
110       * @param status error status - set to error for failure.
111       * @return field number, or negative if field should be skipped.
112       */
113      virtual int32_t handleParseName(const FieldsSet* inheritFrom,
114                                      const U_NAMESPACE_QUALIFIER UnicodeString& name,
115                                      const U_NAMESPACE_QUALIFIER UnicodeString& substr,
116                                      UErrorCode& status);
117
118      /**
119       * Callback interface for subclass.
120       * Base implementation is to call parseValueDefault(...)
121       * @param inheritFrom the set inheriting from - may be null.
122       * @param field which field is being parsed
123       * @param substr the string in question (value side)
124       * @param status error status - set to error for failure.
125       * @see parseValueDefault
126       */
127      virtual void handleParseValue(const FieldsSet* inheritFrom,
128                                    int32_t field,
129                                    const U_NAMESPACE_QUALIFIER UnicodeString& substr,
130                                    UErrorCode& status);
131
132      /**
133       * the default implementation for handleParseValue.
134       * Base implementation is to parse a decimal integer value, or inherit from inheritFrom if the string is 0-length.
135       * Implementations of this function should call set(field,...) on successful parse.
136       * @see handleParseValue
137       */
138      void parseValueDefault(const FieldsSet* inheritFrom,
139                             int32_t field,
140                             const U_NAMESPACE_QUALIFIER UnicodeString& substr,
141                             UErrorCode& status);
142
143
144      /**
145       * convenience implementation for handleParseValue
146       * attempt to load a value from an enum value using udbg_enumByString()
147       * if fails, will call parseValueDefault()
148       * @see handleParseValue
149       */
150      void parseValueEnum(UDebugEnumType type,
151                          const FieldsSet* inheritFrom,
152                          int32_t field,
153                          const U_NAMESPACE_QUALIFIER UnicodeString& substr,
154                          UErrorCode& status);
155
156    private:
157      /**
158       * Not callable - construct a default FieldsSet
159       * @internal
160       */
161      FieldsSet();
162
163      /**
164       * construct the object.
165       * @internal
166       */
167      void construct(UDebugEnumType whichEnum, int32_t fieldCount);
168
169    public:
170    /**
171     * destructor
172     */
173     virtual ~FieldsSet();
174
175    /**
176     * Mark all fields as unset
177     */
178    void clear();
179
180    /**
181     * Mark a specific field as unset
182     * @param field the field to unset
183     */
184    void clear(int32_t field);
185
186    /**
187     * Set a specific field
188     * @param field the field to set (i.e. enum value)
189     * @param value the field's value
190     */
191    void set(int32_t field, int32_t value);
192
193    UBool isSet(int32_t field) const;
194
195    /**
196     * Return the field's value
197     * @param field which field
198     * @return field's value, or -1 if unset.
199     */
200    int32_t get(int32_t field) const;
201
202    /**
203     * Return true if both FieldsSet objects either are based on the same enum, or have the same number of fields.
204     */
205    UBool isSameType(const FieldsSet& other) const;
206
207    /**
208     * @return the number of fields
209     */
210    int32_t fieldCount() const;
211
212    protected:
213       int32_t fValue[U_FIELDS_SET_MAX];
214       UBool fIsSet[U_FIELDS_SET_MAX];
215    protected:
216       int32_t fFieldCount;
217       UDebugEnumType fEnum;
218};
219
220/**
221 * A subclass of FieldsSet representing the fields in a Calendar
222 * @see Calendar
223 */
224class CalendarFieldsSet : public FieldsSet {
225public:
226    CalendarFieldsSet();
227    virtual ~CalendarFieldsSet();
228
229//        void clear(UCalendarDateFields field) { clear((int32_t)field); }
230//        void set(UCalendarDateFields field, int32_t amount) { set ((int32_t)field, amount); }
231
232//        UBool isSet(UCalendarDateFields field) const { return isSet((int32_t)field); }
233//        int32_t get(UCalendarDateFields field) const { return get((int32_t)field); }
234
235    /**
236     * @param matches fillin to hold any fields different. Will have the calendar's value set on them.
237     * @return true if the calendar matches in these fields.
238     */
239    UBool matches(U_NAMESPACE_QUALIFIER Calendar *cal,
240                  CalendarFieldsSet &diffSet,
241                  UErrorCode& status) const;
242
243    /**
244     * For each set field, set the same field on this Calendar.
245     * Doesn't clear the Calendar first.
246     * @param cal Calendar to modify
247     * @param status Contains any errors propagated by the Calendar.
248     */
249    void setOnCalendar(U_NAMESPACE_QUALIFIER Calendar *cal, UErrorCode& status) const;
250
251protected:
252    /**
253     * subclass override
254     */
255    void handleParseValue(const FieldsSet* inheritFrom,
256                          int32_t field,
257                          const U_NAMESPACE_QUALIFIER UnicodeString& substr,
258                          UErrorCode& status);
259};
260
261/**
262 * This class simply implements a set of date and time styles
263 * such as DATE=SHORT  or TIME=SHORT,DATE=LONG, such as would be passed
264 * to DateFormat::createInstance()
265 * @see DateFormat
266 */
267class DateTimeStyleSet : public FieldsSet {
268    public:
269        DateTimeStyleSet();
270        virtual ~DateTimeStyleSet();
271
272        /**
273         * @return the date style, or UDAT_NONE if not set
274         */
275        UDateFormatStyle getDateStyle() const;
276
277        /**
278         * @return the time style, or UDAT_NONE if not set
279         */
280        UDateFormatStyle getTimeStyle() const;
281    protected:
282        void handleParseValue(const FieldsSet* inheritFrom,
283                              int32_t field,
284                              const U_NAMESPACE_QUALIFIER UnicodeString& substr,
285                              UErrorCode& status);
286        int32_t handleParseName(const FieldsSet* inheritFrom,
287                                const U_NAMESPACE_QUALIFIER UnicodeString& name,
288                                const U_NAMESPACE_QUALIFIER UnicodeString& substr,
289                                UErrorCode& status);
290};
291
292
293#endif /*!UCONFIG_NO_FORMAT*/
294#endif /*FLDSET_H_*/
295