aboutsummaryrefslogtreecommitdiff
path: root/src/xz/util.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/xz/util.c89
1 files changed, 45 insertions, 44 deletions
diff --git a/src/xz/util.c b/src/xz/util.c
index 9f9a8fb0..6ab4c2d7 100644
--- a/src/xz/util.c
+++ b/src/xz/util.c
@@ -17,9 +17,45 @@
/// Buffers for uint64_to_str() and uint64_to_nicestr()
static char bufs[4][128];
-/// Thousand separator support in uint64_to_str() and uint64_to_nicestr()
+
+// Thousand separator support in uint64_to_str() and uint64_to_nicestr():
+//
+// DJGPP 2.05 added support for thousands separators but it's broken
+// at least under WinXP with Finnish locale that uses a non-breaking space
+// as the thousands separator. Workaround by disabling thousands separators
+// for DJGPP builds.
+//
+// MSVC doesn't support thousand separators.
+#if defined(__DJGPP__) || defined(_MSC_VER)
+# define FORMAT_THOUSAND_SEP(prefix, suffix) prefix suffix
+# define check_thousand_sep(slot) do { } while (0)
+#else
+# define FORMAT_THOUSAND_SEP(prefix, suffix) ((thousand == WORKS) \
+ ? prefix "'" suffix \
+ : prefix suffix)
+
static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN;
+/// Check if thousands separator is supported. Run-time checking is easiest
+/// because it seems to be sometimes lacking even on a POSIXish system.
+/// Note that trying to use thousands separators when snprintf() doesn't
+/// support them results in undefined behavior. This just has happened to
+/// work well enough in practice.
+///
+/// This must be called before using the FORMAT_THOUSAND_SEP macro.
+static void
+check_thousand_sep(uint32_t slot)
+{
+ if (thousand == UNKNOWN) {
+ bufs[slot][0] = '\0';
+ snprintf(bufs[slot], sizeof(bufs[slot]), "%'u", 1U);
+ thousand = bufs[slot][0] == '1' ? WORKS : BROKEN;
+ }
+
+ return;
+}
+#endif
+
extern void *
xrealloc(void *ptr, size_t size)
@@ -142,31 +178,6 @@ round_up_to_mib(uint64_t n)
}
-/// Check if thousands separator is supported. Run-time checking is easiest
-/// because it seems to be sometimes lacking even on a POSIXish system.
-/// Note that trying to use thousands separators when snprintf() doesn't
-/// support them results in undefined behavior. This just has happened to
-/// work well enough in practice.
-///
-/// DJGPP 2.05 added support for thousands separators but it's broken
-/// at least under WinXP with Finnish locale that uses a non-breaking space
-/// as the thousands separator. Workaround by disabling thousands separators
-/// for DJGPP builds.
-static void
-check_thousand_sep(uint32_t slot)
-{
- if (thousand == UNKNOWN) {
- bufs[slot][0] = '\0';
-#ifndef __DJGPP__
- snprintf(bufs[slot], sizeof(bufs[slot]), "%'u", 1U);
-#endif
- thousand = bufs[slot][0] == '1' ? WORKS : BROKEN;
- }
-
- return;
-}
-
-
extern const char *
uint64_to_str(uint64_t value, uint32_t slot)
{
@@ -174,10 +185,8 @@ uint64_to_str(uint64_t value, uint32_t slot)
check_thousand_sep(slot);
- if (thousand == WORKS)
- snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, value);
- else
- snprintf(bufs[slot], sizeof(bufs[slot]), "%" PRIu64, value);
+ snprintf(bufs[slot], sizeof(bufs[slot]),
+ FORMAT_THOUSAND_SEP("%", PRIu64), value);
return bufs[slot];
}
@@ -201,10 +210,8 @@ uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min,
if ((unit_min == NICESTR_B && value < 10000)
|| unit_max == NICESTR_B) {
// The value is shown as bytes.
- if (thousand == WORKS)
- my_snprintf(&pos, &left, "%'u", (unsigned int)value);
- else
- my_snprintf(&pos, &left, "%u", (unsigned int)value);
+ my_snprintf(&pos, &left, FORMAT_THOUSAND_SEP("%", "u"),
+ (unsigned int)value);
} else {
// Scale the value to a nicer unit. Unless unit_min and
// unit_max limit us, we will show at most five significant
@@ -215,21 +222,15 @@ uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min,
++unit;
} while (unit < unit_min || (d > 9999.9 && unit < unit_max));
- if (thousand == WORKS)
- my_snprintf(&pos, &left, "%'.1f", d);
- else
- my_snprintf(&pos, &left, "%.1f", d);
+ my_snprintf(&pos, &left, FORMAT_THOUSAND_SEP("%", ".1f"), d);
}
static const char suffix[5][4] = { "B", "KiB", "MiB", "GiB", "TiB" };
my_snprintf(&pos, &left, " %s", suffix[unit]);
- if (always_also_bytes && value >= 10000) {
- if (thousand == WORKS)
- snprintf(pos, left, " (%'" PRIu64 " B)", value);
- else
- snprintf(pos, left, " (%" PRIu64 " B)", value);
- }
+ if (always_also_bytes && value >= 10000)
+ snprintf(pos, left, FORMAT_THOUSAND_SEP(" (%", PRIu64 " B)"),
+ value);
return bufs[slot];
}