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