• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2020 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 #include "unicode/utypes.h"
5 
6 #if !UCONFIG_NO_FORMATTING
7 #ifndef __UNITS_DATA_H__
8 #define __UNITS_DATA_H__
9 
10 #include <limits>
11 
12 #include "charstr.h"
13 #include "cmemory.h"
14 #include "unicode/stringpiece.h"
15 #include "unicode/uobject.h"
16 
17 U_NAMESPACE_BEGIN
18 namespace units {
19 
20 /**
21  * Looks up the unit category of a base unit identifier.
22  *
23  * Only supports base units, other units must be resolved to base units before
24  * passing to this function.
25  *
26  * Categories are found in `unitQuantities` in the `units` resource (see
27  * `units.txt`).
28  *
29  * TODO(hugovdm): if we give units_data.cpp access to the functionality of
30  * `extractCompoundBaseUnit` which is currently in units_converter.cpp, we could
31  * support all units for which there is a category. Does it make sense to move
32  * that function to units_data.cpp?
33  */
34 CharString U_I18N_API getUnitCategory(const char *baseUnitIdentifier, UErrorCode &status);
35 
36 /**
37  * Encapsulates "convertUnits" information from units resources, specifying how
38  * to convert from one unit to another.
39  *
40  * Information in this class is still in the form of strings: symbolic constants
41  * need to be interpreted. Rationale: symbols can cancel out for higher
42  * precision conversion - going from feet to inches should cancel out the
43  * `ft_to_m` constant.
44  */
45 class U_I18N_API ConversionRateInfo : public UMemory {
46   public:
ConversionRateInfo()47     ConversionRateInfo() {}
ConversionRateInfo(StringPiece sourceUnit,StringPiece baseUnit,StringPiece factor,StringPiece offset,UErrorCode & status)48     ConversionRateInfo(StringPiece sourceUnit, StringPiece baseUnit, StringPiece factor,
49                        StringPiece offset, UErrorCode &status)
50         : sourceUnit(), baseUnit(), factor(), offset() {
51         this->sourceUnit.append(sourceUnit, status);
52         this->baseUnit.append(baseUnit, status);
53         this->factor.append(factor, status);
54         this->offset.append(offset, status);
55     }
56     CharString sourceUnit;
57     CharString baseUnit;
58     CharString factor;
59     CharString offset;
60 };
61 
62 } // namespace units
63 
64 // Export explicit template instantiations of MaybeStackArray, MemoryPool and
65 // MaybeStackVector. This is required when building DLLs for Windows. (See
66 // datefmt.h, collationiterator.h, erarules.h and others for similar examples.)
67 //
68 // Note: These need to be outside of the units namespace, or Clang will generate
69 // a compile error.
70 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
71 template class U_I18N_API MaybeStackArray<units::ConversionRateInfo*, 8>;
72 template class U_I18N_API MemoryPool<units::ConversionRateInfo, 8>;
73 template class U_I18N_API MaybeStackVector<units::ConversionRateInfo, 8>;
74 #endif
75 
76 namespace units {
77 
78 /**
79  * Returns ConversionRateInfo for all supported conversions.
80  *
81  * @param result Receives the set of conversion rates.
82  * @param status Receives status.
83  */
84 void U_I18N_API getAllConversionRates(MaybeStackVector<ConversionRateInfo> &result, UErrorCode &status);
85 
86 /**
87  * Contains all the supported conversion rates.
88  */
89 class U_I18N_API ConversionRates {
90   public:
91     /**
92      * Constructor
93      *
94      * @param status Receives status.
95      */
ConversionRates(UErrorCode & status)96     ConversionRates(UErrorCode &status) { getAllConversionRates(conversionInfo_, status); }
97 
98     /**
99      * Returns a pointer to the conversion rate info that match the `source`.
100      *
101      * @param source Contains the source.
102      * @param status Receives status.
103      */
104     const ConversionRateInfo *extractConversionInfo(StringPiece source, UErrorCode &status) const;
105 
106   private:
107     MaybeStackVector<ConversionRateInfo> conversionInfo_;
108 };
109 
110 // Encapsulates unitPreferenceData information from units resources, specifying
111 // a sequence of output unit preferences.
112 struct U_I18N_API UnitPreference : public UMemory {
113     // Set geq to 1.0 by default
UnitPreferenceUnitPreference114     UnitPreference() : geq(1.0) {}
115     CharString unit;
116     double geq;
117     UnicodeString skeleton;
118 };
119 
120 /**
121  * Metadata about the preferences in UnitPreferences::unitPrefs_.
122  *
123  * This class owns all of its data.
124  *
125  * UnitPreferenceMetadata lives in the anonymous namespace, because it should
126  * only be useful to internal code and unit testing code.
127  */
128 class U_I18N_API UnitPreferenceMetadata : public UMemory {
129   public:
UnitPreferenceMetadata()130     UnitPreferenceMetadata() {}
131     // Constructor, makes copies of the parameters passed to it.
132     UnitPreferenceMetadata(StringPiece category, StringPiece usage, StringPiece region,
133                            int32_t prefsOffset, int32_t prefsCount, UErrorCode &status);
134 
135     // Unit category (e.g. "length", "mass", "electric-capacitance").
136     CharString category;
137     // Usage (e.g. "road", "vehicle-fuel", "blood-glucose"). Every category
138     // should have an entry for "default" usage. TODO(hugovdm): add a test for
139     // this.
140     CharString usage;
141     // Region code (e.g. "US", "CZ", "001"). Every usage should have an entry
142     // for the "001" region ("world"). TODO(hugovdm): add a test for this.
143     CharString region;
144     // Offset into the UnitPreferences::unitPrefs_ list where the relevant
145     // preferences are found.
146     int32_t prefsOffset;
147     // The number of preferences that form this set.
148     int32_t prefsCount;
149 
150     int32_t compareTo(const UnitPreferenceMetadata &other) const;
151     int32_t compareTo(const UnitPreferenceMetadata &other, bool *foundCategory, bool *foundUsage,
152                       bool *foundRegion) const;
153 };
154 
155 } // namespace units
156 
157 // Export explicit template instantiations of MaybeStackArray, MemoryPool and
158 // MaybeStackVector. This is required when building DLLs for Windows. (See
159 // datefmt.h, collationiterator.h, erarules.h and others for similar examples.)
160 //
161 // Note: These need to be outside of the units namespace, or Clang will generate
162 // a compile error.
163 #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
164 template class U_I18N_API MaybeStackArray<units::UnitPreferenceMetadata*, 8>;
165 template class U_I18N_API MemoryPool<units::UnitPreferenceMetadata, 8>;
166 template class U_I18N_API MaybeStackVector<units::UnitPreferenceMetadata, 8>;
167 template class U_I18N_API MaybeStackArray<units::UnitPreference*, 8>;
168 template class U_I18N_API MemoryPool<units::UnitPreference, 8>;
169 template class U_I18N_API MaybeStackVector<units::UnitPreference, 8>;
170 #endif
171 
172 namespace units {
173 
174 /**
175  * Unit Preferences information for various locales and usages.
176  */
177 class U_I18N_API UnitPreferences {
178   public:
179     /**
180      * Constructor, loads all the preference data.
181      *
182      * @param status Receives status.
183      */
184     UnitPreferences(UErrorCode &status);
185 
186     /**
187      * Returns the set of unit preferences in the particular category that best
188      * matches the specified usage and region.
189      *
190      * If region can't be found, falls back to global (001). If usage can't be
191      * found, falls back to "default".
192      *
193      * @param category The category within which to look up usage and region.
194      * (TODO(hugovdm): improve docs on how to find the category, once the lookup
195      * function is added.)
196      * @param usage The usage parameter. (TODO(hugovdm): improve this
197      * documentation. Add reference to some list of usages we support.) If the
198      * given usage is not found, the method automatically falls back to
199      * "default".
200      * @param region The region whose preferences are desired. If there are no
201      * specific preferences for the requested region, the method automatically
202      * falls back to region "001" ("world").
203      * @param outPreferences A pointer into an array of preferences: essentially
204      * an array slice in combination with preferenceCount.
205      * @param preferenceCount The number of unit preferences that belong to the
206      * result set.
207      * @param status Receives status.
208      *
209      * TODO(hugovdm): maybe replace `UnitPreference **&outPreferences` with a slice class?
210      */
211     void getPreferencesFor(StringPiece category, StringPiece usage, StringPiece region,
212                            const UnitPreference *const *&outPreferences, int32_t &preferenceCount,
213                            UErrorCode &status) const;
214 
215   protected:
216     // Metadata about the sets of preferences, this is the index for looking up
217     // preferences in the unitPrefs_ list.
218     MaybeStackVector<UnitPreferenceMetadata> metadata_;
219     // All the preferences as a flat list: which usage and region preferences
220     // are associated with is stored in `metadata_`.
221     MaybeStackVector<UnitPreference> unitPrefs_;
222 };
223 
224 } // namespace units
225 U_NAMESPACE_END
226 
227 #endif //__UNITS_DATA_H__
228 
229 #endif /* #if !UCONFIG_NO_FORMATTING */
230