]> granicus.if.org Git - icu/commitdiff
Merge branch 'units_router' into younies_units_router_resources
authorHugo van der Merwe <17109322+hugovdm@users.noreply.github.com>
Thu, 19 Mar 2020 12:03:15 +0000 (13:03 +0100)
committerHugo van der Merwe <17109322+hugovdm@users.noreply.github.com>
Thu, 19 Mar 2020 12:03:15 +0000 (13:03 +0100)
1  2 
icu4c/source/i18n/unitsrouter.cpp
icu4c/source/i18n/unitsrouter.h

index 89376c72de1d72f0c382b6d8723d50605a27464f,826f75aba4a6513273be9ee4086dd0ba59dd5e64..a4506be8b9e42333d25e86b1908d16394a3962ed
@@@ -5,12 -5,10 +5,14 @@@
  
  #if !UCONFIG_NO_FORMATTING
  
+ #include <utility>
  #include "cmemory.h"
 +#include "cstring.h"
 +#include "number_decimalquantity.h"
 +#include "resource.h"
  #include "unitsrouter.h"
 +#include "uresimp.h"
  
  U_NAMESPACE_BEGIN
  
@@@ -197,122 -44,17 +199,121 @@@ void putUnitPref(UResourceBundle *usage
  
  } // namespace
  
 +namespace hugovdm_wip {
 +
 +/**
 + * Fetches required data FIXME.
 + *
 + * @param inputUnit the unit for which input is expected. (NOTE/WIP: If this is
 + * known to be a base unit already, we could strip some logic here.)
 + */
 +void getUnitsData(const char *outputRegion, const char *usage, const MeasureUnit &inputUnit,
 +                  CharString &category, MeasureUnit &baseUnit,
 +                  MaybeStackVector<ConversionRateInfo> &conversionInfo,
 +                  MaybeStackVector<UnitPreference> &unitPreferences, UErrorCode &status) {
 +    // One can also use a StackUResourceBundle as a fill-in.
 +    LocalUResourceBundlePointer unitsBundle(ures_openDirect(NULL, "units", &status));
 +    if (U_FAILURE(status)) {
 +        // fprintf(stderr, "%s: ures_openDirect %s\n", u_errorName(status), "units");
 +        return;
 +    }
 +
 +    MeasureUnit inputBase = inputUnit.withSIPrefix(UMEASURE_SI_PREFIX_ONE, status);
 +    if (uprv_strcmp(inputBase.getIdentifier(), "gram") == 0) { inputBase = MeasureUnit::getKilogram(); }
 +    // if (U_FAILURE(status)) fprintf(stderr, "failed getting inputBase: %s\n", u_errorName(status));
 +
 +    StackUResourceBundle convertUnitsBundle;
 +    // CharString has initial capacity 40. Key appending only gets slow when we
 +    // go beyond. TODO(hugovdm): look at how often this might happen though?
 +    // Each append could be a re-allocation.
 +    CharString key;
 +    // key.append("convertUnits/", status);
 +    key.append(inputBase.getIdentifier(), status);
 +    ConvertUnitsSink convertSink(conversionInfo);
 +    ures_getByKey(unitsBundle.getAlias(), "convertUnits", convertUnitsBundle.getAlias(), &status);
 +    ures_getAllItemsWithFallback(convertUnitsBundle.getAlias(), key.data(), convertSink, status);
 +    const CharString &baseIdentifier = conversionInfo[0]->target;
 +    baseUnit = MeasureUnit::forIdentifier(baseIdentifier.data(), status);
 +
 +    // key.clear();
 +    // key.append("unitQuantities/", status);
 +    // key.append(baseIdentifier, status);
 +    // ures_findSubResource(unitsBundle.getAlias(), key.data(), fillIn, &status);
 +    // Now we still need to convert to string.
 +    LocalUResourceBundlePointer unitQuantities(
 +        ures_getByKey(unitsBundle.getAlias(), "unitQuantities", NULL, &status));
 +    int32_t categoryLength;
 +    const UChar *uCategory =
 +        ures_getStringByKey(unitQuantities.getAlias(), baseIdentifier.data(), &categoryLength, &status);
 +    category.appendInvariantChars(uCategory, categoryLength, status);
 +
 +    // We load the region-specific unit preferences into stackBundle, reusing it
 +    // for fill-in every step of the way:
 +    StackUResourceBundle stackBundle;
 +    ures_getByKey(unitsBundle.getAlias(), "unitPreferenceData", stackBundle.getAlias(), &status);
 +    ures_getByKey(stackBundle.getAlias(), category.data(), stackBundle.getAlias(), &status);
 +    if (U_FAILURE(status)) { return; }
 +    ures_getByKey(stackBundle.getAlias(), usage, stackBundle.getAlias(), &status);
 +    if (status == U_MISSING_RESOURCE_ERROR) {
 +        // Requested usage does not exist, use "default".
 +        status = U_ZERO_ERROR;
 +        ures_getByKey(stackBundle.getAlias(), "default", stackBundle.getAlias(), &status);
 +    }
 +    // if (U_FAILURE(status)) fprintf(stderr, "failed getting usage %s: %s\n", usage,
 +    // u_errorName(status));
 +    ures_getByKey(stackBundle.getAlias(), outputRegion, stackBundle.getAlias(), &status);
 +    if (status == U_MISSING_RESOURCE_ERROR) {
 +        // Requested region does not exist, use "001".
 +        status = U_ZERO_ERROR;
 +        ures_getByKey(stackBundle.getAlias(), "001", stackBundle.getAlias(), &status);
 +    }
 +    // if (U_FAILURE(status)) fprintf(stderr, "failed getting region %s: %s\n", outputRegion,
 +    // u_errorName(status));
 +    putUnitPref(stackBundle.getAlias(), unitPreferences, status);
 +    // if (U_FAILURE(status)) fprintf(stderr, "putUnitPref failed: %s\n", u_errorName(status));
 +
 +    // An alterantive for the above "We load ..." block, I don't think this is neater:
 +    // key.clear();
 +    // key.append("unitPreferenceData/", status);
 +    // key.append(category, status).append("/", status);
 +    // key.append(usage, status).append("/", status); // FIXME: fall back to "default"
 +    // key.append(outputRegion, status); // FIXME: fall back to "001"
 +    // UnitPreferencesSink prefsSink(unitPreferences);
 +    // ures_getAllItemsWithFallback(unitsBundle.getAlias(), key.data(), prefsSink, status);
 +
 +    // Load ConversionRateInfo for each of the units in unitPreferences.
 +    //
 +    // WIP/FIXME: this currently adds plenty of duplicates. hugovdm will soon
 +    // adapt the code to skip dupes (or add conversion info for units with SI
 +    // prefixes?)
 +    for (int32_t i = 0; i < unitPreferences.length(); i++) {
 +        UnitPreference *up = unitPreferences[i];
 +        MeasureUnit prefUnitBase = MeasureUnit::forIdentifier(up->unit.data(), status)
 +                                       .withSIPrefix(UMEASURE_SI_PREFIX_ONE, status);
 +        ures_getAllItemsWithFallback(convertUnitsBundle.getAlias(), prefUnitBase.getIdentifier(), convertSink, status);
 +    }
 +}
 +
 +} // namespace hugovdm_wip
 +
  UnitsRouter::UnitsRouter(MeasureUnit inputUnit, StringPiece locale, StringPiece usage,
                           UErrorCode &status) {
 -    StringPiece unitCategory = extractUnitCategory(inputUnit);
 -    MaybeStackVector<UnitPreference> preferences = extractUnitPreferences(locale, usage, unitCategory);
 +    // StringPiece unitCategory = extractUnitCategory(inputUnit);
 +    // MaybeStackVector<UnitPreference> preferences = extractUnitPreferences(locale, usage, unitCategory);
 +    const char *region = "001"; // FIXME extract from locale.
 +    CharString category;
 +    MeasureUnit baseUnit;
 +    MaybeStackVector<ConversionRateInfo> conversionInfo;
 +    MaybeStackVector<UnitPreference> unitPreferences;
 +    getUnitsData(region, usage.data(), inputUnit, category, baseUnit, conversionInfo, unitPreferences,
 +                 status);
  
 -    for (int i = 0, n = preferences.length(); i < n; ++i) {
 -        const auto &preference = *preferences[i];
 -        MeasureUnit complexTargetUnit = MeasureUnit::forIdentifier(preference.identifier, status);
 +    for (int i = 0, n = unitPreferences.length(); i < n; ++i) {
 +        const auto &preference = *unitPreferences[i];
 +        MeasureUnit complexTargetUnit = MeasureUnit::forIdentifier(preference.unit.data(), status);
-         // This fails to compile - it tries to copy a ConverterPreference
-         // instance but converter member has no copy-constructor:
+         // TODO(younies): Find a way to emplaceBack `ConverterPreference`
          // converterPreferences_.emplaceBack(
-         //     ConverterPreference(inputUnit, complexTargetUnit, preference.geq, status));
 -        //     std::move(ConverterPreference(inputUnit, complexTargetUnit, preference.limit, status)));
++        //     std::move(ConverterPreference(inputUnit, complexTargetUnit, preference.geq, status)));
      }
  }
  
@@@ -333,4 -74,4 +333,4 @@@ MaybeStackVector<Measure> UnitsRouter::
  
  U_NAMESPACE_END
  
--#endif /* #if !UCONFIG_NO_FORMATTING */
++#endif /* #if !UCONFIG_NO_FORMATTING */
Simple merge