Skip to content

Commit cbaf886

Browse files
committed
get_config: fix locale-dependent decimal separator in %.17e output
snprintf respects LC_NUMERIC; in de_DE and similar locales it replaces '.' with ',' in float output, producing strings like "8,00e+00" that are not valid TOML. Add h5z_zfp_fmt_double() helper that calls snprintf("%.17e") then replaces the first comma with a dot. Since %.17e places exactly one decimal separator in the mantissa, a single-pass scan suffices. Use it at all four float-formatting sites (rate and accuracy in both the memory-format and header-format paths of get_config).
1 parent 41776a0 commit cbaf886

1 file changed

Lines changed: 23 additions & 4 deletions

File tree

src/H5Zzfp.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,21 @@ H5Z_zfp_set_config(const char *params, unsigned *flags,
10531053
* value as a float rather than an integer (%.17g drops the decimal point for
10541054
* whole numbers like 8.0 → "8", which TOML would read as an integer).
10551055
* --------------------------------------------------------------------------- */
1056+
/* Format a double as %.17e into buf[n] with the decimal separator always '.'
1057+
* regardless of LC_NUMERIC locale. Returns the snprintf-style character count
1058+
* (negative on encoding error, >= n if the buffer was too small). */
1059+
static int
1060+
h5z_zfp_fmt_double(char *buf, size_t n, double val)
1061+
{
1062+
int r = snprintf(buf, n, "%.17e", val);
1063+
char *p;
1064+
/* Some locales (e.g. de_DE) replace '.' with ',' in printf float output.
1065+
* TOML requires '.'; scan and fix the one decimal separator if present. */
1066+
for (p = buf; *p; p++)
1067+
if (*p == ',') { *p = '.'; break; }
1068+
return r;
1069+
}
1070+
10561071
static herr_t
10571072
H5Z_zfp_get_config(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
10581073
char *buf, size_t *buf_size)
@@ -1089,7 +1104,8 @@ H5Z_zfp_get_config(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
10891104
return -1;
10901105
}
10911106
memcpy(&rate, &cd_values[2], sizeof(double));
1092-
nchars = snprintf(tmp, sizeof(tmp), "mode = \"rate\", rate = %.17e", rate);
1107+
{ char d[32]; h5z_zfp_fmt_double(d, sizeof(d), rate);
1108+
nchars = snprintf(tmp, sizeof(tmp), "mode = \"rate\", rate = %s", d); }
10931109
break;
10941110
}
10951111

@@ -1111,7 +1127,8 @@ H5Z_zfp_get_config(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
11111127
return -1;
11121128
}
11131129
memcpy(&acc, &cd_values[2], sizeof(double));
1114-
nchars = snprintf(tmp, sizeof(tmp), "mode = \"accuracy\", acc = %.17e", acc);
1130+
{ char d[32]; h5z_zfp_fmt_double(d, sizeof(d), acc);
1131+
nchars = snprintf(tmp, sizeof(tmp), "mode = \"accuracy\", acc = %s", d); }
11151132
break;
11161133
}
11171134

@@ -1187,7 +1204,8 @@ H5Z_zfp_get_config(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
11871204
zfp_type ztype = Z zfp_field_type(zfld);
11881205
double rate = Z zfp_stream_rate(zstr, ztype, zdims);
11891206
#endif
1190-
nchars = snprintf(tmp, sizeof(tmp), "mode = \"rate\", rate = %.17e", rate);
1207+
{ char d[32]; h5z_zfp_fmt_double(d, sizeof(d), rate);
1208+
nchars = snprintf(tmp, sizeof(tmp), "mode = \"rate\", rate = %s", d); }
11911209
rc = 0;
11921210
break;
11931211
}
@@ -1199,7 +1217,8 @@ H5Z_zfp_get_config(unsigned flags, size_t cd_nelmts, const unsigned cd_values[],
11991217
}
12001218
case zfp_mode_fixed_accuracy: {
12011219
double acc = Z zfp_stream_accuracy(zstr);
1202-
nchars = snprintf(tmp, sizeof(tmp), "mode = \"accuracy\", acc = %.17e", acc);
1220+
{ char d[32]; h5z_zfp_fmt_double(d, sizeof(d), acc);
1221+
nchars = snprintf(tmp, sizeof(tmp), "mode = \"accuracy\", acc = %s", d); }
12031222
rc = 0;
12041223
break;
12051224
}

0 commit comments

Comments
 (0)