// Copy-like constructor; use the default move operators.
DecNum(const DecNum& other, UErrorCode& status);
+ /** Sets the `DecNum` to have the value of another `DecNum`. */
+ void setTo(const DecNum& other, UErrorCode& status);
+
/** Sets the decNumber to the StringPiece. */
void setTo(StringPiece str, UErrorCode& status);
other.fData.getArrayLimit() - other.fData.getArrayStart());
}
+void DecNum::setTo(const DecNum& other, UErrorCode& status) {
+ fContext = other.fContext;
+
+ // Allocate memory for the new DecNum.
+ U_ASSERT(fContext.digits == other.fData.getCapacity());
+ if (fContext.digits > kDefaultDigits) {
+ void* p = fData.resize(fContext.digits, 0);
+ if (p == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ }
+
+ // Copy the data from the old DecNum to the new one.
+ uprv_memcpy(fData.getAlias(), other.fData.getAlias(), sizeof(decNumber));
+ uprv_memcpy(fData.getArrayStart(),
+ other.fData.getArrayStart(),
+ other.fData.getArrayLimit() - other.fData.getArrayStart());
+}
+
void DecNum::setTo(StringPiece str, UErrorCode& status) {
// We need NUL-terminated for decNumber; CharString guarantees this, but not StringPiece.
CharString cstr(str, status);
} // namespace
-UnitConverter::UnitConverter(MeasureUnit source, MeasureUnit target, UErrorCode status) {
+UnitConverter::UnitConverter(MeasureUnit source, MeasureUnit target, UErrorCode status)
+ : conversion_rate_(status) {
+ // TODO(younies):: add the test of non-compound units here.
// Deal with non-compound units only.
- if (source.getCompoundUnits(status).length() > 1 || target.getCompoundUnits(status).length() > 1 ||
- U_FAILURE(status)) {
- status = UErrorCode::U_ILLEGAL_ARGUMENT_ERROR;
- return;
- }
-
- auto sourceUnits = source.getSingleUnits(status);
- auto targetUnits = target.getSingleUnits(status);
+ // if (source.getCompoundUnits(status).length() > 1 || target.getCompoundUnits(status).length() > 1
+ // ||
+ // U_FAILURE(status)) {
+ // status = UErrorCode::U_ILLEGAL_ARGUMENT_ERROR;
+ // return;
+ // }
+
+ // Extract the single units from source and target.
+ auto sourceUnits = source.splitToSingleUnits(status);
+ auto targetUnits = target.splitToSingleUnits(status);
if (U_FAILURE(status)) return;
+
+ // TODO(younies): implement.
}
-decNumber UnitConverter::convert(double quantity, UErrorCode status) {
- DecNum result;
- result.setTo(quantity, status);
+void UnitConverter::convert(const DecNum &input_value, DecNum &output_value, UErrorCode status) {
- result.multiplyBy(this->conversion_rate_.factorNum, status);
- result.divideBy(this->conversion_rate_.factorDen, status);
+ DecNum result(input_value, status);
+ result.multiplyBy(conversion_rate_.factorNum, status);
+ result.divideBy(conversion_rate_.factorDen, status);
+
+ if (U_FAILURE(status)) return;
if (conversion_rate_.reciprocal) {
DecNum reciprocalResult;
reciprocalResult.setTo(1, status);
reciprocalResult.divideBy(result, status);
- return *(reciprocalResult.getRawDecNumber());
+ output_value.setTo(result, status);
+ } else {
+ output_value.setTo(result, status);
}
-
- return *(result.getRawDecNumber());
}
U_NAMESPACE_END
number::impl::DecNum factorNum;
number::impl::DecNum factorDen;
int8_t constants[CONSTANTS_COUNT] = {};
+
+ Factor(UErrorCode &status) {
+ factorNum.setTo(1.0, status);
+ factorDen.setTo(1.0, status);
+ }
};
/**
number::impl::DecNum factorNum;
number::impl::DecNum factorDen;
bool reciprocal;
+
+ ConversionRate(UErrorCode &status) {
+ factorNum.setTo(1.0, status);
+ factorDen.setTo(1.0, status);
+ }
};
/**
class UnitConverter {
public:
/**
- * Constructor for `UnitConverter`.
+ * Constructor of `UnitConverter`.
* NOTE:
* - source and target must be under the same category
* - e.g. meter to mile --> both of them are length units.
+ *
+ * @param source represents the source unit.
+ * @param target represents the target unit.
+ * @param status
*/
UnitConverter(MeasureUnit source, MeasureUnit target, UErrorCode status);
/**
- * Convert quantity in the source unit to the corresponding quantity in the target unit.
+ * Convert a value in the source unit to another value in the target unit.
+ *
+ * @param input_value the value that needs to be converted.
+ * @param output_value the value that holds the result of the conversion.
+ * @param status
*/
- decNumber convert(double quantity, UErrorCode status);
+ void convert(const number::impl::DecNum &input_value, number::impl::DecNum &output_value,
+ UErrorCode status);
private:
ConversionRate conversion_rate_;