From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756904AbcANWYc (ORCPT ); Thu, 14 Jan 2016 17:24:32 -0500 Received: from mga09.intel.com ([134.134.136.24]:57144 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754487AbcANWY2 (ORCPT ); Thu, 14 Jan 2016 17:24:28 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,296,1449561600"; d="scan'208";a="860771610" From: Andy Shevchenko To: Robert Elliott , Matt Fleming , Andrew Morton , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , linux-kernel@vger.kernel.org, Rasmus Villemoes , Brian Norris , Hariprasad S Cc: Andy Shevchenko Subject: [PATCH v2 09/11] lib/vsprintf: use precision field with %pl[From[To]] Date: Fri, 15 Jan 2016 00:23:39 +0200 Message-Id: <1452810221-116505-10-git-send-email-andriy.shevchenko@linux.intel.com> X-Mailer: git-send-email 2.6.4 In-Reply-To: <1452810221-116505-1-git-send-email-andriy.shevchenko@linux.intel.com> References: <1452810221-116505-1-git-send-email-andriy.shevchenko@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The precision field defines how many digits after period ('.') will be printed. Signed-off-by: Andy Shevchenko --- Documentation/printk-formats.txt | 7 +++++++ lib/test_printf.c | 29 +++++++++++++++++++++++++++++ lib/vsprintf.c | 20 +++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 3b41899..534407c 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -295,11 +295,18 @@ unsigned long long value in human-readable form (with IEC binary prefix): %pl 1048575 B (1048575) %plKM 1023 KiB (1048575) %pl 1 MiB (1048576) + %.1plKM 1046527.9 MiB (1097364144125) %plG 2 TiB (2199023255552) For printing given unsigned long long value in human-readable form with automatically choosen IEC binary prefix. + Precision, if passed, defines how many digits will be printed after + period ('.'). In this case the biggest possible unit is used in the + given range [From[To]]. The printed value isn't rounded anyhow. + + For other use cases consider to call string_get_size(). + Passed by reference. bitmap and its derivatives such as cpumask and nodemask: diff --git a/lib/test_printf.c b/lib/test_printf.c index ae35885..4a2e30b 100644 --- a/lib/test_printf.c +++ b/lib/test_printf.c @@ -435,6 +435,30 @@ human_readable(void) { .v = 1048575ULL, .r = "1023 KiB" }, { .v = 1047552ULL, .r = "1023 KiB" }, }; + struct hr_test_data htdpl0KM[] = { + { .v = 1097364144128ULL, .r = "1046528 MiB" }, + { .v = 1097364144125ULL, .r = "1046527 MiB" }, + { .v = 1048578ULL, .r = "1 MiB" }, + { .v = 1048576ULL, .r = "1 MiB" }, + { .v = 1048575ULL, .r = "1023 KiB" }, + { .v = 1047552ULL, .r = "1023 KiB" }, + }; + struct hr_test_data htdpl1KM[] = { + { .v = 1097364144128ULL, .r = "1046528.0 MiB" }, + { .v = 1097364144125ULL, .r = "1046527.9 MiB" }, + { .v = 1048578ULL, .r = "1.0 MiB" }, + { .v = 1048576ULL, .r = "1.0 MiB" }, + { .v = 1048575ULL, .r = "1023.9 KiB" }, + { .v = 1047552ULL, .r = "1023.0 KiB" }, + }; + struct hr_test_data htdpl3KM[] = { + { .v = 1097364144128ULL, .r = "1046528.000 MiB" }, + { .v = 1097364144125ULL, .r = "1046527.999 MiB" }, + { .v = 1048578ULL, .r = "1.000 MiB" }, + { .v = 1048576ULL, .r = "1.000 MiB" }, + { .v = 1048575ULL, .r = "1023.999 KiB" }, + { .v = 1047552ULL, .r = "1023.000 KiB" }, + }; struct hr_test_array { const char *fmt; struct hr_test_data *data; @@ -446,6 +470,11 @@ human_readable(void) { "%plKM", htdplKM, ARRAY_SIZE(htdplKM) }, /* No reversed %pl[To[From]] order */ { "%plMK", htdplM, ARRAY_SIZE(htdplM) }, + { "%.0plKM", htdpl0KM, ARRAY_SIZE(htdpl0KM) }, + { "%.1plKM", htdpl1KM, ARRAY_SIZE(htdpl1KM) }, + { "%.3plKM", htdpl3KM, ARRAY_SIZE(htdpl3KM) }, + /* For now precision is in range [0..3] */ + { "%.4plKM", htdplKM, ARRAY_SIZE(htdplKM) }, }; unsigned int i, j; diff --git a/lib/vsprintf.c b/lib/vsprintf.c index fbcb221..2dd86c9 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1327,7 +1327,9 @@ char *human_readable(char *buf, char *end, const void *addr, to = i; } - if (value) + if (spec.precision >= 0 && spec.precision <= 3 && value) + index = (fls64(value) - 1) / 10; + else if (value) index = __ffs64(value) / 10; else index = 0; @@ -1336,6 +1338,22 @@ char *human_readable(char *buf, char *end, const void *addr, /* Print numeric part */ buf = number(buf, end, value >> (index * 10), default_dec_spec); + /* Print precision part if asked */ + if (spec.precision > 0 && spec.precision <= 3 && index) { + unsigned int remainder; + + remainder = (value >> (index - 1) * 10) % 1024; + for (i = 0; i < spec.precision; i++) + remainder *= 10; + remainder >>= 10; + + /* Period... */ + buf = put_one_char(buf, end, '.'); + + /* ...and remainder part */ + buf = number(buf, end, remainder, spec); + } + /* Space between numeric part and units */ buf = put_one_char(buf, end, ' '); -- 2.6.4