aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-01-17 18:59:15 +0100
committerFlorian Dold <florian.dold@gmail.com>2020-01-17 18:59:15 +0100
commit7378b5a081a0d839c3bd63f6ddd359bca50be695 (patch)
treece62b33d65e6372ea59ae7409b193824735ac538 /src/util
parentac2e40d0491c0f118ff26cb316ec47e0786818e7 (diff)
amount rounding a la Christian
Diffstat (limited to 'src/util')
-rw-r--r--src/util/amount.c16
-rw-r--r--src/util/test_amount.c15
2 files changed, 22 insertions, 9 deletions
diff --git a/src/util/amount.c b/src/util/amount.c
index 48f5d9891..1f00b1d6e 100644
--- a/src/util/amount.c
+++ b/src/util/amount.c
@@ -674,23 +674,27 @@ TALER_amount_divide (struct TALER_Amount *result,
/**
* Round the amount to something that can be transferred on the wire.
+ * The rounding mode is specified via the smallest transferable unit,
+ * which must only have a fractional part.
*
* @param[in,out] amount amount to round down
- * @param max_fractional_digits number of fractional digits to round down to
+ * @param[in] round_unit unit that should be rounded down to,
+ * the value part of this amount must be zero
* @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
* #GNUNET_SYSERR if the amount or currency was invalid
*/
int
TALER_amount_round_down (struct TALER_Amount *amount,
- uint8_t max_fractional_digits)
+ const struct TALER_Amount *round_unit)
{
uint32_t delta;
- uint32_t divisor = 1;
- for (unsigned int i = 0; i < max_fractional_digits; i++)
- divisor *= 10;
+ GNUNET_break (0 == round_unit->value);
- delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / divisor);
+ if (0 == round_unit->fraction)
+ return GNUNET_OK;
+
+ delta = amount->fraction % round_unit->fraction;
if (0 == delta)
return GNUNET_NO;
amount->fraction -= delta;
diff --git a/src/util/test_amount.c b/src/util/test_amount.c
index 4eeccd7e0..3bf8e6fb0 100644
--- a/src/util/test_amount.c
+++ b/src/util/test_amount.c
@@ -31,6 +31,7 @@ main (int argc,
struct TALER_Amount a1;
struct TALER_Amount a2;
struct TALER_Amount a3;
+ struct TALER_Amount r;
char *c;
GNUNET_log_setup ("test-amout",
@@ -237,25 +238,33 @@ main (int argc,
/* test rounding #1 */
GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:0.01",
+ &r));
+
+ GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:4.001",
&a1));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:4",
&a2));
- GNUNET_assert (GNUNET_OK == TALER_amount_round_down (&a1, 2));
- GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, 2));
+ GNUNET_assert (GNUNET_OK == TALER_amount_round_down (&a1, &r));
+ GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, &r));
GNUNET_assert (0 == TALER_amount_cmp (&a1, &a2));
/* test rounding #2 */
GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:0.001",
+ &r));
+
+ GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:4.001",
&a1));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:4.001",
&a2));
- GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, 3));
+ GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, &r));
GNUNET_assert (0 == TALER_amount_cmp (&a1, &a2));
return 0;