summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/i18n/units_data.h
blob: 118458ecca2b0abe02b6d64de668bd49acc8f9a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// © 2020 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING
#ifndef __UNITS_DATA_H__
#define __UNITS_DATA_H__

#include <limits>

#include "charstr.h"
#include "cmemory.h"
#include "unicode/stringpiece.h"
#include "unicode/uobject.h"

U_NAMESPACE_BEGIN
namespace units {

/**
 * Encapsulates "convertUnits" information from units resources, specifying how
 * to convert from one unit to another.
 *
 * Information in this class is still in the form of strings: symbolic constants
 * need to be interpreted. Rationale: symbols can cancel out for higher
 * precision conversion - going from feet to inches should cancel out the
 * `ft_to_m` constant.
 */
class U_I18N_API ConversionRateInfo : public UMemory {
  public:
    ConversionRateInfo() {}
    ConversionRateInfo(StringPiece sourceUnit, StringPiece baseUnit, StringPiece factor,
                       StringPiece offset, UErrorCode &status)
        : sourceUnit(), baseUnit(), factor(), offset() {
        this->sourceUnit.append(sourceUnit, status);
        this->baseUnit.append(baseUnit, status);
        this->factor.append(factor, status);
        this->offset.append(offset, status);
    }
    CharString sourceUnit;
    CharString baseUnit;
    CharString factor;
    CharString offset;
};

} // namespace units

// Export explicit template instantiations of MaybeStackArray, MemoryPool and
// MaybeStackVector. This is required when building DLLs for Windows. (See
// datefmt.h, collationiterator.h, erarules.h and others for similar examples.)
//
// Note: These need to be outside of the units namespace, or Clang will generate
// a compile error.
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
template class U_I18N_API MaybeStackArray<units::ConversionRateInfo*, 8>;
template class U_I18N_API MemoryPool<units::ConversionRateInfo, 8>;
template class U_I18N_API MaybeStackVector<units::ConversionRateInfo, 8>;
#endif

namespace units {

/**
 * Returns ConversionRateInfo for all supported conversions.
 *
 * @param result Receives the set of conversion rates.
 * @param status Receives status.
 */
void U_I18N_API getAllConversionRates(MaybeStackVector<ConversionRateInfo> &result, UErrorCode &status);

/**
 * Contains all the supported conversion rates.
 */
class U_I18N_API ConversionRates {
  public:
    /**
     * Constructor
     *
     * @param status Receives status.
     */
    ConversionRates(UErrorCode &status) { getAllConversionRates(conversionInfo_, status); }

    /**
     * Returns a pointer to the conversion rate info that match the `source`.
     *
     * @param source Contains the source.
     * @param status Receives status.
     */
    const ConversionRateInfo *extractConversionInfo(StringPiece source, UErrorCode &status) const;

  private:
    MaybeStackVector<ConversionRateInfo> conversionInfo_;
};

// Encapsulates unitPreferenceData information from units resources, specifying
// a sequence of output unit preferences.
struct U_I18N_API UnitPreference : public UMemory {
    // Set geq to 1.0 by default
    UnitPreference() : geq(1.0) {}
    CharString unit;
    double geq;
    UnicodeString skeleton;

    UnitPreference(const UnitPreference &other) {
        UErrorCode status = U_ZERO_ERROR;
        this->unit.append(other.unit, status);
        this->geq = other.geq;
        this->skeleton = other.skeleton;
    }
};

/**
 * Metadata about the preferences in UnitPreferences::unitPrefs_.
 *
 * This class owns all of its data.
 *
 * UnitPreferenceMetadata lives in the anonymous namespace, because it should
 * only be useful to internal code and unit testing code.
 */
class U_I18N_API UnitPreferenceMetadata : public UMemory {
  public:
    UnitPreferenceMetadata() {}
    // Constructor, makes copies of the parameters passed to it.
    UnitPreferenceMetadata(StringPiece category, StringPiece usage, StringPiece region,
                           int32_t prefsOffset, int32_t prefsCount, UErrorCode &status);

    // Unit category (e.g. "length", "mass", "electric-capacitance").
    CharString category;
    // Usage (e.g. "road", "vehicle-fuel", "blood-glucose"). Every category
    // should have an entry for "default" usage. TODO(hugovdm): add a test for
    // this.
    CharString usage;
    // Region code (e.g. "US", "CZ", "001"). Every usage should have an entry
    // for the "001" region ("world"). TODO(hugovdm): add a test for this.
    CharString region;
    // Offset into the UnitPreferences::unitPrefs_ list where the relevant
    // preferences are found.
    int32_t prefsOffset;
    // The number of preferences that form this set.
    int32_t prefsCount;

    int32_t compareTo(const UnitPreferenceMetadata &other) const;
    int32_t compareTo(const UnitPreferenceMetadata &other, bool *foundCategory, bool *foundUsage,
                      bool *foundRegion) const;
};

} // namespace units

// Export explicit template instantiations of MaybeStackArray, MemoryPool and
// MaybeStackVector. This is required when building DLLs for Windows. (See
// datefmt.h, collationiterator.h, erarules.h and others for similar examples.)
//
// Note: These need to be outside of the units namespace, or Clang will generate
// a compile error.
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
template class U_I18N_API MaybeStackArray<units::UnitPreferenceMetadata*, 8>;
template class U_I18N_API MemoryPool<units::UnitPreferenceMetadata, 8>;
template class U_I18N_API MaybeStackVector<units::UnitPreferenceMetadata, 8>;
template class U_I18N_API MaybeStackArray<units::UnitPreference*, 8>;
template class U_I18N_API MemoryPool<units::UnitPreference, 8>;
template class U_I18N_API MaybeStackVector<units::UnitPreference, 8>;
#endif

namespace units {

/**
 * Unit Preferences information for various locales and usages.
 */
class U_I18N_API UnitPreferences {
  public:
    /**
     * Constructor, loads all the preference data.
     *
     * @param status Receives status.
     */
    UnitPreferences(UErrorCode &status);

    /**
     * Returns the set of unit preferences in the particular category that best
     * matches the specified usage and region.
     *
     * If region can't be found, falls back to global (001). If usage can't be
     * found, falls back to "default".
     *
     * @param category The category within which to look up usage and region.
     * (TODO(hugovdm): improve docs on how to find the category, once the lookup
     * function is added.)
     * @param usage The usage parameter. (TODO(hugovdm): improve this
     * documentation. Add reference to some list of usages we support.) If the
     * given usage is not found, the method automatically falls back to
     * "default".
     * @param region The region whose preferences are desired. If there are no
     * specific preferences for the requested region, the method automatically
     * falls back to region "001" ("world").
     * @param outPreferences A pointer into an array of preferences: essentially
     * an array slice in combination with preferenceCount.
     * @param preferenceCount The number of unit preferences that belong to the
     * result set.
     * @param status Receives status.
     */
    MaybeStackVector<UnitPreference> getPreferencesFor(StringPiece category, StringPiece usage,
                                                       const Locale &locale,

                                                       UErrorCode &status) const;

  protected:
    // Metadata about the sets of preferences, this is the index for looking up
    // preferences in the unitPrefs_ list.
    MaybeStackVector<UnitPreferenceMetadata> metadata_;
    // All the preferences as a flat list: which usage and region preferences
    // are associated with is stored in `metadata_`.
    MaybeStackVector<UnitPreference> unitPrefs_;
};

} // namespace units
U_NAMESPACE_END

#endif //__UNITS_DATA_H__

#endif /* #if !UCONFIG_NO_FORMATTING */