1 // SPDX-License-Identifier: GPL-2.0-only
3 * Helpers for formatting and printing strings
5 * Copyright 31 August 2008 James Bottomley
6 * Copyright (C) 2013, Intel Corporation
9 #include <linux/kernel.h>
10 #include <linux/math64.h>
11 #include <linux/export.h>
12 #include <linux/ctype.h>
13 #include <linux/device.h>
14 #include <linux/errno.h>
16 #include <linux/limits.h>
17 #include <linux/printbuf.h>
18 #include <linux/slab.h>
19 #include <linux/string.h>
20 #include <linux/string_helpers.h>
23 * string_get_size - get the size in the specified units
24 * @size: The size to be converted in blocks
25 * @blk_size: Size of the block (use 1 for size in bytes)
26 * @units: units to use (powers of 1000 or 1024)
27 * @buf: buffer to format to
28 * @len: length of buffer
30 * This function returns a string formatted to 3 significant figures
31 * giving the size in the required units. @buf should have room for
32 * at least 9 bytes and will always be zero terminated.
35 int string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
38 static const char *const units_10[] = {
39 "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
41 static const char *const units_2[] = {
42 "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"
44 static const char *const *const units_str[] = {
45 [STRING_UNITS_10] = units_10,
46 [STRING_UNITS_2] = units_2,
48 static const unsigned int divisor[] = {
49 [STRING_UNITS_10] = 1000,
50 [STRING_UNITS_2] = 1024,
52 static const unsigned int rounding[] = { 500, 50, 5 };
54 u32 remainder = 0, sf_cap;
65 /* This is Napier's algorithm. Reduce the original block size to
67 * coefficient * divisor[units]^i
69 * we do the reduction so both coefficients are just under 32 bits so
70 * that multiplying them together won't overflow 64 bits and we keep
71 * as much precision as possible in the numbers.
73 * Note: it's safe to throw away the remainders here because all the
74 * precision is in the coefficients.
76 while (blk_size >> 32) {
77 do_div(blk_size, divisor[units]);
82 do_div(size, divisor[units]);
86 /* now perform the actual multiplication keeping i as the sum of the
90 /* and logarithmically reduce it until it's just under the divisor */
91 while (size >= divisor[units]) {
92 remainder = do_div(size, divisor[units]);
96 /* work out in j how many digits of precision we need from the
99 for (j = 0; sf_cap*10 < 1000; j++)
102 if (units == STRING_UNITS_2) {
103 /* express the remainder as a decimal. It's currently the
104 * numerator of a fraction whose denominator is
105 * divisor[units], which is 1 << 10 for STRING_UNITS_2 */
110 /* add a 5 to the digit below what will be printed to ensure
111 * an arithmetical round up and carry it through to size */
112 remainder += rounding[j];
113 if (remainder >= 1000) {
119 snprintf(tmp, sizeof(tmp), ".%03u", remainder);
124 if (i >= ARRAY_SIZE(units_2))
127 unit = units_str[units][i];
129 return snprintf(buf, len, "%u%s %s", (u32)size, tmp, unit);
131 EXPORT_SYMBOL(string_get_size);