mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-14 17:24:01 +00:00
Merge pull request #45 from hugovdm/usagefix
Support usage component dropping, and more
This commit is contained in:
commit
6b14d7f1a0
3 changed files with 39 additions and 39 deletions
|
@ -259,10 +259,9 @@ class UnitPreferencesSink : public ResourceSink {
|
|||
MaybeStackVector<UnitPreferenceMetadata> *metadata;
|
||||
};
|
||||
|
||||
int32_t binarySearch(const MaybeStackVector<UnitPreferenceMetadata> *metadata, const char *category,
|
||||
const char *usage, const char *region, bool *foundCategory, bool *foundUsage,
|
||||
int32_t binarySearch(const MaybeStackVector<UnitPreferenceMetadata> *metadata,
|
||||
const UnitPreferenceMetadata &desired, bool *foundCategory, bool *foundUsage,
|
||||
bool *foundRegion, UErrorCode &status) {
|
||||
UnitPreferenceMetadata desired(category, usage, region, -1, -1, status);
|
||||
if (U_FAILURE(status)) { return -1; }
|
||||
int32_t start = 0;
|
||||
int32_t end = metadata->length();
|
||||
|
@ -285,21 +284,15 @@ int32_t binarySearch(const MaybeStackVector<UnitPreferenceMetadata> *metadata, c
|
|||
|
||||
/**
|
||||
* Finds the UnitPreferenceMetadata instance that matches the given category,
|
||||
* usage and region: if missing, region falls back to "001", and usage falls
|
||||
* back to "default".
|
||||
*
|
||||
* This is implemented as a binary search, with fallback restarting the search
|
||||
* from the search range at which the parent in the category/usage/region
|
||||
* hierarchy was found.
|
||||
* usage and region: if missing, region falls back to "001", and usage
|
||||
* repeatedly drops tailing components, eventually trying "default"
|
||||
* ("land-agriculture-grain" -> "land-agriculture" -> "land" -> "default").
|
||||
*
|
||||
* @param metadata The full list of UnitPreferenceMetadata instances.
|
||||
* @param category The category to search for. If category is not known, it can
|
||||
* be resolved from the baseunit of the input (for supported unit categories).
|
||||
* TODO(hugovdm): implement the unit->category lookup (via "unitQuantities" in
|
||||
* the units resource bundle).
|
||||
* @param category The category to search for. See getUnitCategory().
|
||||
* @param usage The usage for which formatting preferences is needed. If the
|
||||
* given usage is not known, this function automatically falls back to "default"
|
||||
* usage.
|
||||
* given usage is not known, automatic fallback occurs, see function description
|
||||
* above.
|
||||
* @param region The region for which preferences are needed. If there are no
|
||||
* region-specific preferences, this function automatically falls back to the
|
||||
* "001" region (global).
|
||||
|
@ -315,37 +308,38 @@ int32_t getPreferenceMetadataIndex(const MaybeStackVector<UnitPreferenceMetadata
|
|||
UErrorCode &status) {
|
||||
if (U_FAILURE(status)) { return -1; }
|
||||
bool foundCategory, foundUsage, foundRegion;
|
||||
int32_t idx = binarySearch(metadata, category, usage, region, &foundCategory, &foundUsage,
|
||||
&foundRegion, status);
|
||||
UnitPreferenceMetadata desired(category, usage, region, -1, -1, status);
|
||||
int32_t idx = binarySearch(metadata, desired, &foundCategory, &foundUsage, &foundRegion, status);
|
||||
if (U_FAILURE(status)) { return -1; }
|
||||
if (idx >= 0) { return idx; }
|
||||
if (!foundCategory) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return idx;
|
||||
return -1;
|
||||
}
|
||||
U_ASSERT(foundCategory);
|
||||
if (!foundUsage) {
|
||||
if (uprv_strcmp(usage, "default") != 0) {
|
||||
usage = "default";
|
||||
idx = binarySearch(metadata, category, usage, region, &foundCategory, &foundUsage,
|
||||
&foundRegion, status);
|
||||
}
|
||||
if (!foundUsage) {
|
||||
while (!foundUsage) {
|
||||
int32_t lastDashIdx = desired.usage.lastIndexOf('-');
|
||||
if (lastDashIdx > 0) {
|
||||
desired.usage.truncate(lastDashIdx);
|
||||
} else if (uprv_strcmp(desired.usage.data(), "default") != 0) {
|
||||
desired.usage.truncate(0).append("default", status);
|
||||
} else {
|
||||
status = U_MISSING_RESOURCE_ERROR;
|
||||
return idx;
|
||||
return -1;
|
||||
}
|
||||
idx = binarySearch(metadata, desired, &foundCategory, &foundUsage, &foundRegion, status);
|
||||
if (U_FAILURE(status)) { return -1; }
|
||||
}
|
||||
U_ASSERT(foundCategory);
|
||||
U_ASSERT(foundUsage);
|
||||
if (!foundRegion) {
|
||||
if (uprv_strcmp(region, "001") != 0) {
|
||||
region = "001";
|
||||
idx = binarySearch(metadata, category, usage, region, &foundCategory, &foundUsage,
|
||||
&foundRegion, status);
|
||||
if (uprv_strcmp(desired.region.data(), "001") != 0) {
|
||||
desired.region.truncate(0).append("001", status);
|
||||
idx = binarySearch(metadata, desired, &foundCategory, &foundUsage, &foundRegion, status);
|
||||
}
|
||||
if (!foundRegion) {
|
||||
status = U_MISSING_RESOURCE_ERROR;
|
||||
return idx;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
U_ASSERT(foundCategory);
|
||||
|
|
|
@ -106,12 +106,15 @@ namespace {
|
|||
/**
|
||||
* 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(const char *category, const char *usage, const char *region,
|
||||
int32_t prefsOffset, int32_t prefsCount, UErrorCode &status);
|
||||
|
||||
|
@ -139,9 +142,6 @@ class U_I18N_API UnitPreferenceMetadata : public UMemory {
|
|||
|
||||
/**
|
||||
* Unit Preferences information for various locales and usages.
|
||||
*
|
||||
* TODO(hugovdm): add a function to look up the category based on the input
|
||||
* unit.
|
||||
*/
|
||||
class U_I18N_API UnitPreferences {
|
||||
public:
|
||||
|
@ -153,12 +153,11 @@ class U_I18N_API UnitPreferences {
|
|||
UnitPreferences(UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Returns the set of unit preferences in the particular cateogry that best
|
||||
* 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". Copies the preferences structures.
|
||||
* TODO(hugovdm/review): Consider returning pointers (references) instead?
|
||||
* 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
|
||||
|
@ -170,10 +169,13 @@ class U_I18N_API UnitPreferences {
|
|||
* @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 The vector to which preferences will be added.
|
||||
* @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.
|
||||
*
|
||||
* TODO: maybe replace `UnitPreference **&outPrefrences` with a slice class?
|
||||
* TODO(hugovdm): maybe replace `UnitPreference **&outPrefrences` with a slice class?
|
||||
*/
|
||||
void getPreferencesFor(const char *category, const char *usage, const char *region,
|
||||
const UnitPreference *const *&outPreferences, int32_t &preferenceCount,
|
||||
|
|
|
@ -103,6 +103,10 @@ void UnitsDataTest::testGetPreferences() {
|
|||
{"XX default falls back to 001", "length", "default", "XX", WorldLenMax, WorldLenMin},
|
||||
{"Unknown usage US", "length", "foobar", "US", USLenMax, USLenMin},
|
||||
{"Unknown usage 001", "length", "foobar", "XX", WorldLenMax, WorldLenMin},
|
||||
{"Fallback", "length", "person-height-xyzzy", "DE", "meter-and-centimeter",
|
||||
"meter-and-centimeter"},
|
||||
{"Fallback twice", "length", "person-height-xyzzy-foo", "DE", "meter-and-centimeter",
|
||||
"meter-and-centimeter"},
|
||||
};
|
||||
IcuTestErrorCode status(*this, "testGetPreferences");
|
||||
UnitPreferencesOpenedUp preferences(status);
|
||||
|
|
Loading…
Add table
Reference in a new issue