exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit c2c2c116755c2cc6ebcac07ad1dc6012ba660ff1
parent a54e194b360bec01fb404a369abf88b0c65b54a9
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 15 Mar 2026 22:33:14 +0100

new amount set logic for #11253

Diffstat:
Msrc/include/taler/taler_amount_lib.h | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/util/amount.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 158 insertions(+), 0 deletions(-)

diff --git a/src/include/taler/taler_amount_lib.h b/src/include/taler/taler_amount_lib.h @@ -483,6 +483,69 @@ TALER_amount_round_down (struct TALER_Amount *amount, const struct TALER_Amount *round_unit); +/** + * Represents a set of amounts in different currencies. + * Useful when adding up various amounts in different + * currencies. + */ +struct TALER_AmountSet +{ + /** + * Array of amounts. Each currency should have at most one entry. + */ + struct TALER_Amount *taa; + + /** + * Length of the @e taa array. + */ + unsigned int taa_size; + +}; + + +/** + * Free memory allocated within @a as, but not @a as itself. + * Effectively sets the total amount in @a as also back to zero. + * + * @param[in,out] as set to free (turned into an empty set) + */ +void +TALER_amount_set_free (struct TALER_AmountSet *as); + + +/** + * Add amount @a a to the total amount represented by @a as. + * + * @param[in,out] as set of amounts to update by adding @a a + * @param val amount to add + * @param cap cap for the sums to enforce, can be NULL; + * if given, then #TALER_AAR_INVALID_RESULT_OVERFLOW is impossible + * as we will use @a cap as a maximum value for this currency + * @return operation status, negative on failures; + * #TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE is impossible, + * except if @a cap does not match @a val + */ +enum TALER_AmountArithmeticResult +TALER_amount_set_add (struct TALER_AmountSet *as, + const struct TALER_Amount *val, + const struct TALER_Amount *cap); + + +/** + * Test if the amount @a b is available in @a as, that is if + * the total amount added to @a as in the currency of @a b + * is not below @a b. In other words, returns true if + * the available amount in @a as would suffice to pay for @a b. + * + * @param as set to compare + * @param b amount to check if it falls into the range + * @return true if b <= as(b.currency) + */ +bool +TALER_amount_set_test_above (const struct TALER_AmountSet *as, + const struct TALER_Amount *b); + + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/util/amount.c b/src/util/amount.c @@ -849,4 +849,99 @@ TALER_amount_round_down (struct TALER_Amount *amount, } +void +TALER_amount_set_free (struct TALER_AmountSet *as) +{ + GNUNET_array_grow (as->taa, + as->taa_size, + 0); +} + + +enum TALER_AmountArithmeticResult +TALER_amount_set_add (struct TALER_AmountSet *as, + const struct TALER_Amount *val, + const struct TALER_Amount *cap) +{ + for (unsigned int i = 0; i<as->taa_size; i++) + { + struct TALER_Amount *ai = &as->taa[i]; + enum TALER_AmountArithmeticResult aar; + + if (GNUNET_OK != + TALER_amount_cmp_currency (ai, + val)) + continue; + aar = TALER_amount_add (ai, + ai, + val); + /* If we have a cap, we tolerate the overflow */ + if ( (aar < 0) && + ( (NULL == cap) || + (TALER_AAR_INVALID_RESULT_OVERFLOW != aar) ) ) + return aar; /* hard error */ + if (TALER_AAR_INVALID_RESULT_OVERFLOW == aar) + { + if (GNUNET_OK != + TALER_amount_cmp_currency (val, + cap)) + return TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE; + *ai = *cap; + return (TALER_amount_is_zero (cap)) + ? TALER_AAR_RESULT_ZERO + : TALER_AAR_RESULT_POSITIVE; + } + GNUNET_assert (aar >= 0); + if (NULL != cap) + GNUNET_assert (GNUNET_OK == + TALER_amount_min (ai, + ai, + cap)); + return; + } + GNUNET_array_append (as->taa, + as->taa_size, + *val); + { + struct TALER_Amount *ai = &as->taa[as->taa_size - 1]; + + if (NULL != cap) + { + if (GNUNET_OK != + TALER_amount_cmp_currency (val, + cap)) + return TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE; + GNUNET_assert (GNUNET_OK == + TALER_amount_min (ai, + ai, + cap)); + } + return (TALER_amount_is_zero (ai)) + ? TALER_AAR_RESULT_ZERO + : TALER_AAR_RESULT_POSITIVE; + } +} + + +bool +TALER_amount_set_test_above (const struct TALER_AmountSet *as, + const struct TALER_Amount *b) +{ + for (unsigned int i = 0; i<as->taa_size; i++) + { + const struct TALER_Amount *asi = &as->taa[i]; + + if (GNUNET_OK != + TALER_amount_cmp_currency (b, + asi)) + continue; + if (1 != + TALER_amount_cmp (b, + asi)) + return true; + } + return false; +} + + /* end of amount.c */