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