gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: parser for INI configuration of


From: gnunet
Subject: [taler-exchange] branch master updated: parser for INI configuration of DD51 currency specifications
Date: Sat, 07 Oct 2023 21:03:10 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 4c4e5f9c parser for INI configuration of DD51 currency specifications
4c4e5f9c is described below

commit 4c4e5f9cb4faf71c304060b0622a7b43b6280fb2
Author: Christian Grothoff <grothoff@gnunet.org>
AuthorDate: Sat Oct 7 21:03:07 2023 +0200

    parser for INI configuration of DD51 currency specifications
---
 src/include/taler_util.h |  77 ++++++++++++++
 src/util/config.c        | 257 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 334 insertions(+)

diff --git a/src/include/taler_util.h b/src/include/taler_util.h
index 77cb5859..66951e12 100644
--- a/src/include/taler_util.h
+++ b/src/include/taler_util.h
@@ -209,6 +209,83 @@ TALER_config_get_currency (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
                            char **currency);
 
 
+/**
+ * Details about how to render a currency.
+ */
+struct TALER_CurrencySpecification
+{
+  /**
+   * Name of the currency.
+   */
+  char currency[TALER_CURRENCY_LEN];
+
+  /**
+   * Character used to separate decimals.  String as
+   * multi-byte sequences may be required (UTF-8!).
+   */
+  char *decimal_separator;
+
+  /**
+   * how many digits the user may enter at most after the @e decimal_separator
+   */
+  unsigned int num_fractional_input_digits;
+
+  /**
+   * how many digits we render in normal scale after the @e decimal_separator
+   */
+  unsigned int num_fractional_normal_digits;
+
+  /**
+   * how many digits we render in after the @e decimal_separator even if all
+   * remaining digits are zero.
+   */
+  unsigned int num_fractional_trailing_zero_digits;
+
+  /**
+   * True to put the currency symbol before the number,
+   * false to put the currency symbol after the number.
+   */
+  bool is_currency_name_leading;
+
+  /**
+   * Mapping of powers of 10 to alternative currency names or symbols.
+   * Keys are the decimal powers, values the currency symbol to use.
+   * Map MUST contain an entry for "0" to the default currency symbol.
+   */
+  json_t *map_alt_unit_names;
+
+};
+
+
+/**
+ * Parse information about supported currencies from
+ * our configuration.
+ *
+ * @param cfg configuration to parse
+ * @param[out] num_currencies set to number of enabled currencies, length of 
@e cspecs
+ * @param[out] cspecs set to currency specification array
+ * @return #GNUNET_OK on success, #GNUNET_NO if zero
+ *  currency specifications were enabled,
+ *  #GNUNET_SYSERR if the configuration was malformed
+ */
+enum GNUNET_GenericReturnValue
+TALER_CONFIG_parse_currencies (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                               unsigned int *num_currencies,
+                               struct TALER_CurrencySpecification **cspecs);
+
+
+/**
+ * Free @a cspecs array.
+ *
+ * @param num_currencies length of @a cspecs array
+ * @param[in] cspecs array to free
+ */
+void
+TALER_CONFIG_free_currencies (
+  unsigned int num_currencies,
+  struct TALER_CurrencySpecification cspecs[static num_currencies]);
+
+
 /**
  * Allow user to specify an amount on the command line.
  *
diff --git a/src/util/config.c b/src/util/config.c
index c0079246..125ea7b1 100644
--- a/src/util/config.c
+++ b/src/util/config.c
@@ -166,3 +166,260 @@ TALER_config_get_currency (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
     }
   return GNUNET_OK;
 }
+
+
+/**
+ * Closure for #parse_currencies_cb().
+ */
+struct CurrencyParserContext
+{
+  /**
+   * Current offset in @e cspecs.
+   */
+  unsigned int num_currencies;
+
+  /**
+   * Length of the @e cspecs array.
+   */
+  unsigned int len_cspecs;
+
+  /**
+   * Array of currency specifications (see DD 51).
+   */
+  struct TALER_CurrencySpecification *cspecs;
+
+  /**
+   * Configuration we are parsing.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Set to true if the configuration was malformed.
+   */
+  bool failure;
+};
+
+
+/**
+ * Function to iterate over section.
+ *
+ * @param cls closure with a `struct CurrencyParserContext *`
+ * @param section name of the section
+ */
+static void
+parse_currencies_cb (void *cls,
+                     const char *section)
+{
+  struct CurrencyParserContext *cpc = cls;
+  struct TALER_CurrencySpecification *cspec;
+  unsigned long long num;
+  char *str;
+
+  if (cpc->failure)
+    return;
+  if (0 != strncasecmp (section,
+                        "currency-",
+                        strlen ("currency-")))
+    return; /* not interesting */
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_yesno (cpc->cfg,
+                                            section,
+                                            "ENABLED"))
+    return; /* disabled */
+  if (cpc->len_cspecs == cpc->num_currencies)
+  {
+    GNUNET_array_grow (cpc->cspecs,
+                       cpc->len_cspecs,
+                       cpc->len_cspecs * 2 + 4);
+  }
+  cspec = &cpc->cspecs[cpc->num_currencies++];
+  cspec->is_currency_name_leading
+    = GNUNET_CONFIGURATION_get_value_yesno (cpc->cfg,
+                                            section,
+                                            "NAME_LEADING");
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cpc->cfg,
+                                             section,
+                                             "NAME",
+                                             &str))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "NAME");
+    cpc->failure = true;
+    return;
+  }
+  if (strlen (str) >= TALER_CURRENCY_LEN)
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "NAME",
+                               "Name given is too long");
+    cpc->failure = true;
+    GNUNET_free (str);
+    return;
+  }
+  strcpy (cspec->currency,
+          str);
+  GNUNET_free (str);
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cpc->cfg,
+                                             section,
+                                             "DECIMAL_SEPARATOR",
+                                             &str))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "DECIMAL_SEPARATOR");
+    cpc->failure = true;
+    return;
+  }
+  cspec->decimal_separator = str;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cpc->cfg,
+                                             section,
+                                             "FRACTIONAL_INPUT_DIGITS",
+                                             &num))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "FRACTIONAL_INPUT_DIGITS");
+    cpc->failure = true;
+    return;
+  }
+  if (num > TALER_AMOUNT_FRAC_LEN)
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "FRACTIONAL_INPUT_DIGITS",
+                               "Number given is too big");
+    cpc->failure = true;
+    return;
+  }
+  cspec->num_fractional_input_digits = num;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cpc->cfg,
+                                             section,
+                                             "FRACTIONAL_NORMAL_DIGITS",
+                                             &num))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "FRACTIONAL_NORMAL_DIGITS");
+    cpc->failure = true;
+    return;
+  }
+  if (num > TALER_AMOUNT_FRAC_LEN)
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "FRACTIONAL_NORMAL_DIGITS",
+                               "Number given is too big");
+    cpc->failure = true;
+    return;
+  }
+  cspec->num_fractional_normal_digits = num;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cpc->cfg,
+                                             section,
+                                             "FRACTIONAL_TRAILING_ZERO_DIGITS",
+                                             &num))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "FRACTIONAL_TRAILING_ZERO_DIGITS");
+    cpc->failure = true;
+    return;
+  }
+  if (num > TALER_AMOUNT_FRAC_LEN)
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "FRACTIONAL_TRAILING_ZERO_DIGITS",
+                               "Number given is too big");
+    cpc->failure = true;
+    return;
+  }
+  cspec->num_fractional_trailing_zero_digits = num;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cpc->cfg,
+                                             section,
+                                             "ALT_UNIT_NAMES",
+                                             &str))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               section,
+                               "ALT_UNIT_NAMES");
+    cpc->failure = true;
+    return;
+  }
+  {
+    json_error_t err;
+
+    cspec->map_alt_unit_names = json_loads (str,
+                                            JSON_REJECT_DUPLICATES,
+                                            &err);
+    GNUNET_free (str);
+    if (NULL == cspec->map_alt_unit_names)
+    {
+      GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                                 section,
+                                 "ALT_UNIT_NAMES",
+                                 err.text);
+      cpc->failure = true;
+      return;
+    }
+  }
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_CONFIG_parse_currencies (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                               unsigned int *num_currencies,
+                               struct TALER_CurrencySpecification **cspecs)
+{
+  struct CurrencyParserContext cpc = {
+    .cfg = cfg
+  };
+
+  GNUNET_CONFIGURATION_iterate_sections (cfg,
+                                         &parse_currencies_cb,
+                                         &cpc);
+  if (cpc.failure)
+  {
+    GNUNET_array_grow (cpc.cspecs,
+                       cpc.len_cspecs,
+                       0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_array_grow (cpc.cspecs,
+                     cpc.len_cspecs,
+                     cpc.num_currencies);
+  *num_currencies = cpc.num_currencies;
+  *cspecs = cpc.cspecs;
+  if (0 == *num_currencies)
+    return GNUNET_NO;
+  return GNUNET_OK;
+}
+
+
+void
+TALER_CONFIG_free_currencies (
+  unsigned int num_currencies,
+  struct TALER_CurrencySpecification cspecs[static num_currencies])
+{
+  for (unsigned int i = 0; i<num_currencies; i++)
+  {
+    struct TALER_CurrencySpecification *cspec = &cspecs[i];
+
+    GNUNET_free (cspec->decimal_separator);
+    json_decref (cspec->map_alt_unit_names);
+  }
+  GNUNET_array_grow (cspecs,
+                     num_currencies,
+                     0);
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]