2008-08-31 19:13:54 +04:00
/*
* Helpers for formatting and printing strings
*
* Copyright 31 August 2008 James Bottomley
*/
# include <linux/kernel.h>
# include <linux/math64.h>
2011-11-17 06:29:17 +04:00
# include <linux/export.h>
2008-08-31 19:13:54 +04:00
# 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 )
{
2012-05-30 02:07:32 +04:00
static const char * units_10 [ ] = { " B " , " kB " , " MB " , " GB " , " TB " , " PB " ,
2008-08-31 19:13:54 +04:00
" EB " , " ZB " , " YB " , NULL } ;
2012-05-30 02:07:32 +04:00
static const char * units_2 [ ] = { " B " , " KiB " , " MiB " , " GiB " , " TiB " , " PiB " ,
2008-08-31 19:13:54 +04:00
" EiB " , " ZiB " , " YiB " , NULL } ;
2012-05-30 02:07:32 +04:00
static const char * * units_str [ ] = {
2008-08-31 19:13:54 +04:00
[ STRING_UNITS_10 ] = units_10 ,
[ STRING_UNITS_2 ] = units_2 ,
} ;
2012-05-30 02:07:32 +04:00
static const unsigned int divisor [ ] = {
2008-08-31 19:13:54 +04:00
[ STRING_UNITS_10 ] = 1000 ,
[ STRING_UNITS_2 ] = 1024 ,
} ;
int i , j ;
u64 remainder = 0 , sf_cap ;
char tmp [ 8 ] ;
tmp [ 0 ] = ' \0 ' ;
2008-10-14 22:34:21 +04:00
i = 0 ;
if ( size > = divisor [ units ] ) {
while ( size > = divisor [ units ] & & units_str [ units ] [ i ] ) {
remainder = do_div ( size , divisor [ units ] ) ;
i + + ;
}
2008-08-31 19:13:54 +04:00
2008-10-14 22:34:21 +04:00
sf_cap = size ;
for ( j = 0 ; sf_cap * 10 < 1000 ; j + + )
sf_cap * = 10 ;
2008-08-31 19:13:54 +04:00
2008-10-14 22:34:21 +04:00
if ( j ) {
remainder * = 1000 ;
do_div ( remainder , divisor [ units ] ) ;
snprintf ( tmp , sizeof ( tmp ) , " .%03lld " ,
( unsigned long long ) remainder ) ;
tmp [ j + 1 ] = ' \0 ' ;
}
2008-08-31 19:13:54 +04:00
}
2008-10-14 22:34:21 +04:00
snprintf ( buf , len , " %lld%s %s " , ( unsigned long long ) size ,
2008-08-31 19:13:54 +04:00
tmp , units_str [ units ] [ i ] ) ;
return 0 ;
}
EXPORT_SYMBOL ( string_get_size ) ;