#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
} // 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)));
}
}
U_NAMESPACE_END
--#endif /* #if !UCONFIG_NO_FORMATTING */
++#endif /* #if !UCONFIG_NO_FORMATTING */