diff --git a/glib/gutils.c b/glib/gutils.c index e84d8accf..32c5796e4 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -2180,6 +2180,8 @@ g_format_size (guint64 size) * suffixes. IEC units should only be used for reporting things with * a strong "power of 2" basis, like RAM sizes or RAID stripe sizes. * Network and storage sizes should be reported in the normal SI units. + * @G_FORMAT_SIZE_BITS: set the size as a quantity in bits, rather than + * bytes, and return units in bits. For example, ‘Mb’ rather than ‘MB’. * * Flags to modify the format of the string returned by g_format_size_full(). */ @@ -2215,10 +2217,12 @@ g_format_size_full (guint64 size, typedef enum { FORMAT_BYTES, - FORMAT_BYTES_IEC + FORMAT_BYTES_IEC, + FORMAT_BITS, + FORMAT_BITS_IEC } FormatIndex; - const struct Format formats[2][6] = { + const struct Format formats[4][6] = { { { KILOBYTE_FACTOR, N_("%.1f kB") }, { MEGABYTE_FACTOR, N_("%.1f MB") }, @@ -2234,6 +2238,22 @@ g_format_size_full (guint64 size, { TEBIBYTE_FACTOR, N_("%.1f TiB") }, { PEBIBYTE_FACTOR, N_("%.1f PiB") }, { EXBIBYTE_FACTOR, N_("%.1f EiB") } + }, + { + { 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") } } }; @@ -2242,14 +2262,22 @@ g_format_size_full (guint64 size, string = g_string_new (NULL); - - if (flags & G_FORMAT_SIZE_IEC_UNITS) - { - index = FORMAT_BYTES_IEC; - } - else + switch (flags & ~G_FORMAT_SIZE_LONG_FORMAT) { + case G_FORMAT_SIZE_DEFAULT: index = FORMAT_BYTES; + break; + case (G_FORMAT_SIZE_DEFAULT | G_FORMAT_SIZE_IEC_UNITS): + index = FORMAT_BYTES_IEC; + break; + case G_FORMAT_SIZE_BITS: + index = FORMAT_BITS; + break; + case (G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS): + index = FORMAT_BITS_IEC; + break; + default: + g_assert_not_reached (); } @@ -2261,6 +2289,10 @@ g_format_size_full (guint64 size, { format = g_dngettext (GETTEXT_PACKAGE, "%u byte", "%u bytes", (guint) size); } + else + { + format = g_dngettext (GETTEXT_PACKAGE, "%u bit", "%u bits", (guint) size); + } g_string_printf (string, format, (guint) size); @@ -2312,19 +2344,27 @@ g_format_size_full (guint64 size, */ guint plural_form = size < 1000 ? size : size % 1000 + 1000; - /* Second problem: we need to translate the string "%u byte" and - * "%u bytes" for pluralisation, but the correct number format to + /* Second problem: we need to translate the string "%u byte/bit" and + * "%u bytes/bits" for pluralisation, but the correct number format to * use for a gsize is different depending on which architecture * we're on. * - * Solution: format the number separately and use "%s bytes" on + * Solution: format the number separately and use "%s bytes/bits" on * all platforms. */ const gchar *translated_format; gchar *formatted_number; - /* Translators: the %s in "%s bytes" will always be replaced by a number. */ - translated_format = g_dngettext(GETTEXT_PACKAGE, "%s byte", "%s bytes", plural_form); + if (index == FORMAT_BYTES || index == FORMAT_BYTES_IEC) + { + /* Translators: the %s in "%s bytes" will always be replaced by a number. */ + translated_format = g_dngettext (GETTEXT_PACKAGE, "%s byte", "%s bytes", plural_form); + } + else + { + /* Translators: the %s in "%s bits" will always be replaced by a number. */ + translated_format = g_dngettext (GETTEXT_PACKAGE, "%s bit", "%s bits", plural_form); + } /* XXX: Windows doesn't support the "'" format modifier, so we * must not use it there. Instead, just display the number * without separation. Bug #655336 is open until a solution is diff --git a/glib/gutils.h b/glib/gutils.h index 356c64370..c48699aaa 100644 --- a/glib/gutils.h +++ b/glib/gutils.h @@ -181,7 +181,8 @@ typedef enum { G_FORMAT_SIZE_DEFAULT = 0, G_FORMAT_SIZE_LONG_FORMAT = 1 << 0, - G_FORMAT_SIZE_IEC_UNITS = 1 << 1 + G_FORMAT_SIZE_IEC_UNITS = 1 << 1, + G_FORMAT_SIZE_BITS = 1 << 2 } GFormatSizeFlags; GLIB_AVAILABLE_IN_2_30 diff --git a/glib/tests/fileutils.c b/glib/tests/fileutils.c index 2fe22cc0e..78fca7dd2 100644 --- a/glib/tests/fileutils.c +++ b/glib/tests/fileutils.c @@ -551,6 +551,36 @@ test_format_size_for_display (void) check_string (g_format_size_full (238472938, G_FORMAT_SIZE_IEC_UNITS), "227.4 MiB"); check_string (g_format_size_full (238472938, G_FORMAT_SIZE_DEFAULT), "238.5 MB"); check_string (g_format_size_full (238472938, G_FORMAT_SIZE_LONG_FORMAT), "238.5 MB (238472938 bytes)"); + + + check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS), "0 bits"); + check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS), "1 bit"); + check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS), "2 bits"); + + check_string (g_format_size_full (2000ULL, G_FORMAT_SIZE_BITS), "2.0 kb"); + check_string (g_format_size_full (2000ULL * 1000, G_FORMAT_SIZE_BITS), "2.0 Mb"); + check_string (g_format_size_full (2000ULL * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0 Gb"); + check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0 Tb"); + check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0 Pb"); + check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0 Eb"); + + check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS), "238.5 Mb"); + check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_LONG_FORMAT), "238.5 Mb (238472938 bits)"); + + + check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "0 bits"); + check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "1 bit"); + check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2 bits"); + + check_string (g_format_size_full (2048ULL, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0 Kib"); + check_string (g_format_size_full (2048ULL * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0 Mib"); + check_string (g_format_size_full (2048ULL * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0 Gib"); + check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0 Tib"); + check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0 Pib"); + check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0 Eib"); + + check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "227.4 Mib"); + check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_LONG_FORMAT), "227.4 Mib (238472938 bits)"); } static void