+static size_t
+fmt_type_to_cc_index (enum fmt_type type)
+{
+ switch (type)
+ {
+ case FMT_CCA: return 0;
+ case FMT_CCB: return 1;
+ case FMT_CCC: return 2;
+ case FMT_CCD: return 3;
+ case FMT_CCE: return 4;
+ default: NOT_REACHED ();
+ }
+}
+
+/* Returns the number formatting style associated with the given
+ format TYPE. */
+const struct fmt_number_style *
+fmt_settings_get_style (const struct fmt_settings *settings,
+ enum fmt_type type)
+{
+ verify (FMT_F < 6);
+ verify (FMT_COMMA < 6);
+ verify (FMT_DOT < 6);
+ verify (FMT_DOLLAR < 6);
+ verify (FMT_PCT < 6);
+ verify (FMT_E < 6);
+
+#define OPPOSITE(C) ((C) == ',' ? '.' : ',')
+#define AFFIX(S) { .s = (char *) (S), .width = sizeof (S) - 1 }
+#define NS(PREFIX, SUFFIX, DECIMAL, GROUPING, INCLUDE_LEADING_ZERO) { \
+ .neg_prefix = AFFIX ("-"), \
+ .prefix = AFFIX (PREFIX), \
+ .suffix = AFFIX (SUFFIX), \
+ .neg_suffix = AFFIX (""), \
+ .decimal = DECIMAL, \
+ .grouping = GROUPING, \
+ .include_leading_zero = INCLUDE_LEADING_ZERO \
+ }
+#define ANS(DECIMAL, GROUPING, INCLUDE_LEADING_ZERO) { \
+ [FMT_F] = NS( "", "", DECIMAL, 0, INCLUDE_LEADING_ZERO), \
+ [FMT_E] = NS( "", "", DECIMAL, 0, INCLUDE_LEADING_ZERO), \
+ [FMT_COMMA] = NS( "", "", DECIMAL, GROUPING, INCLUDE_LEADING_ZERO), \
+ [FMT_DOT] = NS( "", "", GROUPING, DECIMAL, INCLUDE_LEADING_ZERO), \
+ [FMT_DOLLAR] = NS("$", "", DECIMAL, GROUPING, false), \
+ [FMT_PCT] = NS( "", "%", DECIMAL, 0, false), \
+ }
+#define ANS2(DECIMAL, GROUPING) { \
+ ANS(DECIMAL, GROUPING, false), \
+ ANS(DECIMAL, GROUPING, true), \
+ }
+
+ /* First index: 0 for ',' decimal point, 1 for '.' decimal point.
+ Second index: 0 for no leading zero, 1 for leading zero.
+ Third index: TYPE.
+ */
+ static const struct fmt_number_style styles[2][2][6] = {
+ ANS2 (',', '.'),
+ ANS2 ('.', ','),
+ };
+
+ static const struct fmt_number_style default_style = NS ("", "", '.', 0, false);
+
+ switch (type)
+ {
+ case FMT_F:
+ case FMT_COMMA:
+ case FMT_DOT:
+ case FMT_DOLLAR:
+ case FMT_PCT:
+ case FMT_E:
+ {
+ int decimal_idx = settings->decimal == '.';
+ int leadzero_idx = settings->include_leading_zero;
+ return &styles[decimal_idx][leadzero_idx][type];
+ }
+
+ case FMT_CCA:
+ case FMT_CCB:
+ case FMT_CCC:
+ case FMT_CCD:
+ case FMT_CCE:
+ {
+ size_t idx = fmt_type_to_cc_index (type);
+ return settings->ccs[idx] ? settings->ccs[idx] : &default_style;
+ }