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