blob: b6fe8e88de3c2ef71cbe7e2f793d5537133d138b [file] [log] [blame]
Victor Changce4bf3c2021-01-19 16:34:24 +00001// © 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
17U_NAMESPACE_BEGIN
18namespace 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 */
34CharString 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 */
45class U_I18N_API ConversionRateInfo : public UMemory {
46 public:
47 ConversionRateInfo() {}
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
71template class U_I18N_API MaybeStackArray<units::ConversionRateInfo*, 8>;
72template class U_I18N_API MemoryPool<units::ConversionRateInfo, 8>;
73template class U_I18N_API MaybeStackVector<units::ConversionRateInfo, 8>;
74#endif
75
76namespace 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 */
84void U_I18N_API getAllConversionRates(MaybeStackVector<ConversionRateInfo> &result, UErrorCode &status);
85
86/**
87 * Contains all the supported conversion rates.
88 */
89class U_I18N_API ConversionRates {
90 public:
91 /**
92 * Constructor
93 *
94 * @param status Receives status.
95 */
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.
112struct U_I18N_API UnitPreference : public UMemory {
113 // Set geq to 1.0 by default
114 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 */
128class U_I18N_API UnitPreferenceMetadata : public UMemory {
129 public:
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
164template class U_I18N_API MaybeStackArray<units::UnitPreferenceMetadata*, 8>;
165template class U_I18N_API MemoryPool<units::UnitPreferenceMetadata, 8>;
166template class U_I18N_API MaybeStackVector<units::UnitPreferenceMetadata, 8>;
167template class U_I18N_API MaybeStackArray<units::UnitPreference*, 8>;
168template class U_I18N_API MemoryPool<units::UnitPreference, 8>;
169template class U_I18N_API MaybeStackVector<units::UnitPreference, 8>;
170#endif
171
172namespace units {
173
174/**
175 * Unit Preferences information for various locales and usages.
176 */
177class 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
225U_NAMESPACE_END
226
227#endif //__UNITS_DATA_H__
228
229#endif /* #if !UCONFIG_NO_FORMATTING */