Blame view

lib/string_helpers.c 1.66 KB
3c9f3681d   James Bottomley   [SCSI] lib: add g...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  /*
   * Helpers for formatting and printing strings
   *
   * Copyright 31 August 2008 James Bottomley
   */
  #include <linux/kernel.h>
  #include <linux/math64.h>
  #include <linux/module.h>
  #include <linux/string_helpers.h>
  
  /**
   * string_get_size - get the size in the specified units
   * @size:	The size to be converted
   * @units:	units to use (powers of 1000 or 1024)
   * @buf:	buffer to format to
   * @len:	length of buffer
   *
   * This function returns a string formatted to 3 significant figures
   * giving the size in the required units.  Returns 0 on success or
   * error on failure.  @buf is always zero terminated.
   *
   */
  int string_get_size(u64 size, const enum string_size_units units,
  		    char *buf, int len)
  {
a8659597b   H. Peter Anvin   [SCSI] lib: strin...
26
  	const char *units_10[] = { "B", "kB", "MB", "GB", "TB", "PB",
3c9f3681d   James Bottomley   [SCSI] lib: add g...
27
28
29
30
31
32
33
  				   "EB", "ZB", "YB", NULL};
  	const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB",
  				 "EiB", "ZiB", "YiB", NULL };
  	const char **units_str[] = {
  		[STRING_UNITS_10] =  units_10,
  		[STRING_UNITS_2] = units_2,
  	};
a8659597b   H. Peter Anvin   [SCSI] lib: strin...
34
  	const unsigned int divisor[] = {
3c9f3681d   James Bottomley   [SCSI] lib: add g...
35
36
37
38
39
40
41
42
  		[STRING_UNITS_10] = 1000,
  		[STRING_UNITS_2] = 1024,
  	};
  	int i, j;
  	u64 remainder = 0, sf_cap;
  	char tmp[8];
  
  	tmp[0] = '\0';
a8659597b   H. Peter Anvin   [SCSI] lib: strin...
43
44
45
46
47
48
  	i = 0;
  	if (size >= divisor[units]) {
  		while (size >= divisor[units] && units_str[units][i]) {
  			remainder = do_div(size, divisor[units]);
  			i++;
  		}
3c9f3681d   James Bottomley   [SCSI] lib: add g...
49

a8659597b   H. Peter Anvin   [SCSI] lib: strin...
50
51
52
  		sf_cap = size;
  		for (j = 0; sf_cap*10 < 1000; j++)
  			sf_cap *= 10;
3c9f3681d   James Bottomley   [SCSI] lib: add g...
53

a8659597b   H. Peter Anvin   [SCSI] lib: strin...
54
55
56
57
58
59
60
  		if (j) {
  			remainder *= 1000;
  			do_div(remainder, divisor[units]);
  			snprintf(tmp, sizeof(tmp), ".%03lld",
  				 (unsigned long long)remainder);
  			tmp[j+1] = '\0';
  		}
3c9f3681d   James Bottomley   [SCSI] lib: add g...
61
  	}
a8659597b   H. Peter Anvin   [SCSI] lib: strin...
62
  	snprintf(buf, len, "%lld%s %s", (unsigned long long)size,
3c9f3681d   James Bottomley   [SCSI] lib: add g...
63
64
65
66
67
  		 tmp, units_str[units][i]);
  
  	return 0;
  }
  EXPORT_SYMBOL(string_get_size);