From 51f9c95cf240b7de4c1db8e4dcb7e18d72ba0d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Dejean?= Date: Fri, 20 Oct 2017 18:46:47 +0200 Subject: [PATCH] utils: refactor g_format_size_full Refactor g_format_size_full to avoid duplicate code and make it easier to add more units. https://bugzilla.gnome.org/show_bug.cgi?id=789170 --- glib/gutils.c | 125 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 45 deletions(-) diff --git a/glib/gutils.c b/glib/gutils.c index eb44f179f..39898ec31 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -2197,63 +2197,98 @@ gchar * g_format_size_full (guint64 size, GFormatSizeFlags flags) { + struct Format + { + guint64 factor; + const char string[8]; + }; + + struct FormatPlural + { + const char singular[8]; + const char plural[9]; + }; + + typedef enum + { + FORMAT_BYTES, + FORMAT_BYTES_IEC + } FormatIndex; + + struct FormatPlural format_plurals[2] = + { + { N_("%u byte"), N_("%u bytes") }, + { N_("%u byte"), N_("%u bytes") } + }; + + struct Format formats[2][6] = { + { + { KILOBYTE_FACTOR, N_("%.1f kB") }, + { MEGABYTE_FACTOR, N_("%.1f MB") }, + { GIGABYTE_FACTOR, N_("%.1f GB") }, + { TERABYTE_FACTOR, N_("%.1f TB") }, + { PETABYTE_FACTOR, N_("%.1f PB") }, + { EXABYTE_FACTOR, N_("%.1f EB") } + }, + { + { KIBIBYTE_FACTOR, N_("%.1f KiB") }, + { MEBIBYTE_FACTOR, N_("%.1f MiB") }, + { GIBIBYTE_FACTOR, N_("%.1f GiB") }, + { TEBIBYTE_FACTOR, N_("%.1f TiB") }, + { PEBIBYTE_FACTOR, N_("%.1f PiB") }, + { EXBIBYTE_FACTOR, N_("%.1f EiB") } + } + }; + GString *string; + FormatIndex index; string = g_string_new (NULL); + if (flags & G_FORMAT_SIZE_IEC_UNITS) { - if (size < KIBIBYTE_FACTOR) - { - g_string_printf (string, - g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes", (guint) size), - (guint) size); - flags &= ~G_FORMAT_SIZE_LONG_FORMAT; - } - - else if (size < MEBIBYTE_FACTOR) - g_string_printf (string, _("%.1f KiB"), (gdouble) size / (gdouble) KIBIBYTE_FACTOR); - else if (size < GIBIBYTE_FACTOR) - g_string_printf (string, _("%.1f MiB"), (gdouble) size / (gdouble) MEBIBYTE_FACTOR); - - else if (size < TEBIBYTE_FACTOR) - g_string_printf (string, _("%.1f GiB"), (gdouble) size / (gdouble) GIBIBYTE_FACTOR); - - else if (size < PEBIBYTE_FACTOR) - g_string_printf (string, _("%.1f TiB"), (gdouble) size / (gdouble) TEBIBYTE_FACTOR); - - else if (size < EXBIBYTE_FACTOR) - g_string_printf (string, _("%.1f PiB"), (gdouble) size / (gdouble) PEBIBYTE_FACTOR); - - else - g_string_printf (string, _("%.1f EiB"), (gdouble) size / (gdouble) EXBIBYTE_FACTOR); + index = FORMAT_BYTES_IEC; } else { - if (size < KILOBYTE_FACTOR) + index = FORMAT_BYTES; + } + + + if (size < formats[index][0].factor) + { + const struct FormatPlural * const f = &format_plurals[index]; + g_string_printf (string, + g_dngettext (GETTEXT_PACKAGE, + _(f->singular), + _(f->plural), + (guint) size), + (guint) size); + flags &= ~G_FORMAT_SIZE_LONG_FORMAT; + } + else + { + const gsize n = G_N_ELEMENTS (formats[index]); + gsize i; + + /* + * Point the last format (the highest unit) by default + * and then then scan all formats, starting with the 2nd one + * because the 1st is already managed by with the plural form + */ + const struct Format * f = &formats[index][n - 1]; + + for (i = 1; i < n; i++) { - g_string_printf (string, - g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes", (guint) size), - (guint) size); - flags &= ~G_FORMAT_SIZE_LONG_FORMAT; + if (size < formats[index][i].factor) + { + f = &formats[index][i - 1]; + break; + } } - else if (size < MEGABYTE_FACTOR) - g_string_printf (string, _("%.1f kB"), (gdouble) size / (gdouble) KILOBYTE_FACTOR); - - else if (size < GIGABYTE_FACTOR) - g_string_printf (string, _("%.1f MB"), (gdouble) size / (gdouble) MEGABYTE_FACTOR); - - else if (size < TERABYTE_FACTOR) - g_string_printf (string, _("%.1f GB"), (gdouble) size / (gdouble) GIGABYTE_FACTOR); - else if (size < PETABYTE_FACTOR) - g_string_printf (string, _("%.1f TB"), (gdouble) size / (gdouble) TERABYTE_FACTOR); - - else if (size < EXABYTE_FACTOR) - g_string_printf (string, _("%.1f PB"), (gdouble) size / (gdouble) PETABYTE_FACTOR); - - else - g_string_printf (string, _("%.1f EB"), (gdouble) size / (gdouble) EXABYTE_FACTOR); + g_string_printf (string, _(f->string), (gdouble) size / (gdouble) f->factor); } if (flags & G_FORMAT_SIZE_LONG_FORMAT)