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