blob: 3dcc8ef7f518af3187d8929a4a0e1a5560a589e6 [file] [log] [blame]
// © 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
#include "number_usageprefs.h"
#include "cstring.h"
#include "number_decimalquantity.h"
#include "number_microprops.h"
#include "number_roundingutils.h"
#include "unicode/char16ptr.h"
#include "unicode/currunit.h"
#include "unicode/fmtable.h"
#include "unicode/measure.h"
#include "unicode/numberformatter.h"
#include "unicode/platform.h"
#include "unicode/unum.h"
#include "unicode/urename.h"
using namespace icu::number;
using namespace icu::number::impl;
// Copy constructor
Usage::Usage(const Usage &other) : fUsage(nullptr), fLength(other.fLength), fError(other.fError) {
if (other.fUsage != nullptr) {
fUsage = (char *)uprv_malloc(fLength + 1);
uprv_strncpy(fUsage, other.fUsage, fLength + 1);
}
}
// Copy assignment operator
Usage &Usage::operator=(const Usage &other) {
fLength = other.fLength;
if (other.fUsage != nullptr) {
fUsage = (char *)uprv_malloc(fLength + 1);
uprv_strncpy(fUsage, other.fUsage, fLength + 1);
}
fError = other.fError;
return *this;
}
// Move constructor - can it be improved by taking over src's "this" instead of
// copying contents? Swapping pointers makes sense for heap objects but not for
// stack objects.
// *this = std::move(src);
Usage::Usage(Usage &&src) U_NOEXCEPT : fUsage(src.fUsage), fLength(src.fLength), fError(src.fError) {
// Take ownership away from src if necessary
src.fUsage = nullptr;
}
// Move assignment operator
Usage &Usage::operator=(Usage &&src) U_NOEXCEPT {
if (this == &src) {
return *this;
}
if (fUsage != nullptr) {
uprv_free(fUsage);
}
fUsage = src.fUsage;
fLength = src.fLength;
fError = src.fError;
// Take ownership away from src if necessary
src.fUsage = nullptr;
return *this;
}
Usage::~Usage() {
if (fUsage != nullptr) {
uprv_free(fUsage);
fUsage = nullptr;
}
}
void Usage::set(StringPiece value) {
if (fUsage != nullptr) {
uprv_free(fUsage);
fUsage = nullptr;
}
fLength = value.length();
fUsage = (char *)uprv_malloc(fLength + 1);
uprv_strncpy(fUsage, value.data(), fLength);
fUsage[fLength] = 0;
}
UsagePrefsHandler::UsagePrefsHandler(const Locale &locale,
const MeasureUnit inputUnit,
const StringPiece usage,
const MicroPropsGenerator *parent,
UErrorCode &status)
: fUnitsRouter(inputUnit, StringPiece(locale.getCountry()), usage, status),
fParent(parent) {
}
void UsagePrefsHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micros,
UErrorCode &status) const {
fParent->processQuantity(quantity, micros, status);
if (U_FAILURE(status)) {
return;
}
quantity.roundToInfinity(); // Enables toDouble
auto routed = fUnitsRouter.route(quantity.toDouble(), status);
micros.outputUnit = routed[0]->getUnit();
quantity.setToDouble(routed[0]->getNumber().getDouble());
// TODO(units): here we are always overriding Precision. (1) get precision
// from fUnitsRouter, (2) ensure we use the UnitPreference skeleton's
// precision only when there isn't an explicit override we prefer to use.
// This needs to be handled within
// NumberFormatterImpl::macrosToMicroGenerator in number_formatimpl.cpp
Precision precision = Precision::integer().withMinDigits(2);
UNumberFormatRoundingMode roundingMode;
// Temporary until ICU 64?
roundingMode = precision.fRoundingMode;
CurrencyUnit currency(u"", status);
micros.rounder = {precision, roundingMode, currency, status};
if (U_FAILURE(status)) {
return;
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */