]> granicus.if.org Git - icu/commitdiff
add essential functionality to DecNum and fix the skeleton
authorYounies <younies.mahmoud@gmail.com>
Tue, 4 Feb 2020 13:39:50 +0000 (14:39 +0100)
committerYounies <younies.mahmoud@gmail.com>
Tue, 4 Feb 2020 13:39:50 +0000 (14:39 +0100)
icu4c/source/i18n/number_decnum.h
icu4c/source/i18n/number_utils.cpp
icu4c/source/i18n/unitconverter.cpp
icu4c/source/i18n/unitconverter.h

index b1a3245caeb36a31a93899d174a47e9eaf868a71..d01a6573871bd1e395fe10e12c4a4433d36bb13e 100644 (file)
@@ -33,6 +33,9 @@ class U_I18N_API DecNum : public UMemory {
     // 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);
 
index 1c3ba5da9cbbcd08fc039d787eb6ee424ee94b08..a656f237f712a623575615180e9f1cb4a5d63200 100644 (file)
@@ -117,6 +117,26 @@ DecNum::DecNum(const DecNum& other, 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);
index 82c2216ea0cf4f84dd78d177d717bf88683559ac..46cde80bd3119adc5c19c873aee8bb5b57c195e1 100644 (file)
@@ -167,35 +167,42 @@ void loadConversionRate(Factor &conversionFactor, StringPiece source, StringPiec
 
 } // 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
index b27cb553140434f3710ae0604198238d5bfd3ad8..e9e2b7e5d62e74cdcb0bcf66d05c6128e39df887 100644 (file)
@@ -31,6 +31,11 @@ struct Factor {
     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);
+    }
 };
 
 /**
@@ -42,6 +47,11 @@ struct ConversionRate {
     number::impl::DecNum factorNum;
     number::impl::DecNum factorDen;
     bool reciprocal;
+
+    ConversionRate(UErrorCode &status) {
+        factorNum.setTo(1.0, status);
+        factorDen.setTo(1.0, status);
+    }
 };
 
 /**
@@ -50,17 +60,26 @@ struct ConversionRate {
 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_;