]> git.nbdom.net Git - nb.git/commitdiff
Bed
authorNicolas Boisselier <nicolas.boisselier@gmail.com>
Fri, 2 Sep 2016 00:13:04 +0000 (01:13 +0100)
committerNicolas Boisselier <nicolas.boisselier@gmail.com>
Fri, 2 Sep 2016 00:13:04 +0000 (01:13 +0100)
etc/profile.d/nb.sh
lib/perl/Number/Bytes/Human.pm [new file with mode: 0644]

index 3dbedd271537a61acd7f0e33e25cc8382946a726..14e73827a5400b5558e2018514137aa530b67cfe 100644 (file)
@@ -1,6 +1,7 @@
 nb_repos_status() {
   shell_help "List repos git status" "$@" && return
   local status
+  local pwd=`pwd`
   for i in $(nb-repo-dirs); do
     cd "$i" || continue
 
@@ -9,6 +10,7 @@ nb_repos_status() {
 
     printf ">%s%s\n" "$i" "$status"
   done
+  cd "$pwd"
 }
 
 nb_auth() {
diff --git a/lib/perl/Number/Bytes/Human.pm b/lib/perl/Number/Bytes/Human.pm
new file mode 100644 (file)
index 0000000..e917fda
--- /dev/null
@@ -0,0 +1,751 @@
+package Number::Bytes::Human;
+
+use strict;
+use warnings;
+
+our $VERSION = '0.10';
+
+require Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT_OK = qw(format_bytes parse_bytes);
+
+require POSIX;
+use Carp qw(croak carp);
+
+#my $DEFAULT_BLOCK = 1024;
+#my $DEFAULT_ZERO = '0';
+#my $DEFAULT_ROUND_STYLE = 'ceil';
+my %DEFAULT_SUFFIXES = (
+  1024 => ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
+  1000 => ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
+  1024000 => ['', 'M', 'T', 'E', 'Y'],
+  si_1024 => ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'],
+  si_1000 => ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
+);
+my @DEFAULT_PREFIXES = @{$DEFAULT_SUFFIXES{1024}};
+
+sub _default_suffixes {
+  my $set = shift || 1024;
+  if (exists $DEFAULT_SUFFIXES{$set}) {
+    return @{$DEFAULT_SUFFIXES{$set}} if wantarray;
+    return [ @{$DEFAULT_SUFFIXES{$set}} ];
+  }
+  croak "unknown suffix set '$set'";
+}
+
+my %ROUND_FUNCTIONS = (
+  ceil => sub { return POSIX::ceil($_[0] * (10 ** $_[1])) / 10**$_[1]; },
+  floor => sub { return POSIX::floor($_[0] * (10 ** $_[1])) / 10**$_[1]; },
+  round => sub { return sprintf( "%." . ( $_[1] || 0 ) . "f", $_[0] ); },
+  trunc => sub { return sprintf( "%d", $_[0] * (10 ** $_[1])) / 10**$_[1]; },
+  # what about 'ceiling'?
+);
+
+sub _round_function {
+  my $style = shift;
+  if (exists $ROUND_FUNCTIONS{$style}) {
+    return $ROUND_FUNCTIONS{$style}
+  }
+  croak "unknown round style '$style'";
+}
+
+# options
+#   block | block_size | base | bs => 1024 | 1000
+#   base_1024 | block_1024 | 1024 => $true
+#   base_1000 | block_1000 | 1000 => $true
+#
+#   round_function => \&
+#   round_style => 'ceiling', 'round', 'floor', 'trunc'
+#
+#   suffixes => 1024 | 1000 | si_1024 | si_1000 | 1024000 | \@
+#   si => 1
+#   unit => string (eg., 'B' | 'bps' | 'b')
+#
+#   zero => '0' (default) | '-' | '0%S' | undef
+#
+#
+#   supress_point_zero | no_point_zero =>
+#   b_to_i => 1
+#   to_s => \&
+#
+#   allow_minus => 0 | 1
+#   too_large => string
+#   quiet => 1 (supresses "too large number" warning)
+
+
+
+#  PROBABLY CRAP:
+#   precision => integer
+
+# parsed options
+#   BLOCK => 1024 | 1000
+#   ROUND_STYLE => 'ceil', 'round', 'floor', 'trunc'
+#   ROUND_FUNCTION => \&
+#   SUFFIXES => \@
+#   ZERO =>
+#   SI => undef | 1                    Parse SI compatible
+
+
+=begin private
+
+  $options = _parse_args($seed, $args)
+  $options = _parse_args($seed, arg1 => $val1, ...)
+
+$seed is undef or a hashref
+$args is a hashref
+
+=end private
+
+=cut
+
+sub _parse_args {
+  my $seed = shift;
+  my %args;
+
+  my %options;
+  unless (defined $seed) { # use defaults
+    $options{BLOCK} = 1024;
+    $options{ROUND_STYLE} = 'ceil';
+    $options{ROUND_FUNCTION} = _round_function($options{ROUND_STYLE});
+    $options{ZERO} = '0';
+    $options{SI} = undef;
+    $options{PRECISION} = 1;
+    $options{PRECISION_CUTOFF} = 1;
+    #$options{SUFFIXES} = # deferred to the last minute when we know BLOCK, seek [**]
+    $options{UNIT} = undef;
+  }
+  # else { %options = %$seed } # this is set if @_!=0, down below
+
+  if (@_==0) { # quick return for default values (no customized args)
+    return (defined $seed) ? $seed : \%options;
+  } elsif (@_==1 && ref $_[0]) { # \%args
+    %args = %{$_[0]};
+  } else { # arg1 => $val1, arg2 => $val2
+    %args = @_;
+  }
+
+  # this is done here so this assignment/copy doesn't happen if @_==0
+  %options = %$seed unless %options;
+
+# block | block_size | base | bs => 1024 | 1000
+# block_1024 | base_1024 | 1024 => $true
+# block_1000 | base_1000 | 1024 => $true
+  if ($args{block} ||
+      $args{block_size} ||
+      $args{base} ||
+      $args{bs}
+    ) {
+    my $block = $args{block} ||
+                $args{block_size} ||
+                $args{base} ||
+                $args{bs};
+    unless ($block==1000 || $block==1024 || $block==1_024_000) {
+      croak "invalid base: $block (should be 1024, 1000 or 1024000)";
+    }
+    $options{BLOCK} = $block;
+
+  } elsif ($args{block_1024} ||
+           $args{base_1024}  ||
+           $args{1024}) {
+
+    $options{BLOCK} = 1024;
+  } elsif ($args{block_1000} ||
+           $args{base_1000}  ||
+           $args{1000}) {
+
+    $options{BLOCK} = 1000;
+  }
+
+# round_function => \&
+# round_style => 'ceil' | 'floor' | 'round' | 'trunc'
+  if ($args{round_function}) {
+    unless (ref $args{round_function} eq 'CODE') {
+      croak "round function ($args{round_function}) should be a code ref";
+    }
+    $options{ROUND_FUNCTION} = $args{round_function};
+    $options{ROUND_STYLE} = $args{round_style} || 'unknown';
+  } elsif ($args{round_style}) {
+    $options{ROUND_FUNCTION} = _round_function($args{round_style});
+    $options{ROUND_STYLE} = $args{round_style};
+  }
+
+# SI compatibility (mostly for parsing)
+  if ($args{si}) {
+    $options{SI} = 1;
+  }
+
+# suffixes => 1024 | 1000 | si_1024 | si_1000 | 1024000 | \@
+  if ($args{suffixes}) {
+    if (ref $args{suffixes} eq 'ARRAY') {
+      $options{SUFFIXES} = $args{suffixes};
+    } elsif ($args{suffixes} =~ /^(si_)?(1000|1024)$/) {
+      $options{SUFFIXES} = _default_suffixes($args{suffixes});
+    } else {
+      croak "suffixes ($args{suffixes}) should be 1024, 1000, si_1024, si_1000, 1024000 or an array ref";
+    }
+  }
+  if (defined $args{unit}) {
+    $options{UNIT} = $args{unit};
+  }
+
+# zero => undef | string
+  if (exists $args{zero}) {
+    $options{ZERO} = $args{zero};
+    if (defined $options{ZERO}) {
+      $options{ZERO} =~ s/%S/$options{SUFFIXES}->[0]/g
+    }
+  }
+
+# precision => <integer>
+  if (exists $args{precision} and $args{precision} =~ /\A\d+\z/) {
+    $options{PRECISION} = $args{precision};
+  }
+
+# precision_cutoff => <intenger>
+  if (exists $args{precision_cutoff} and ($args{precision_cutoff} =~ /\A\d+\z/ or $args{precision_cutoff} = '-1')) {
+    $options{PRECISION_CUTOFF} = $args{precision_cutoff};
+  }
+
+# quiet => 1
+  if ($args{quiet}) {
+    $options{QUIET} = 1;
+  }
+
+  if (defined $seed) {
+    %$seed = %options;
+    return $seed;
+  }
+  return \%options
+}
+
+# NOTE. _format_bytes() SHOULD not change $options - NEVER.
+
+sub _format_bytes {
+  my $bytes = shift;
+  return undef unless defined $bytes;
+  my $options = shift;
+  my %options = %$options;
+
+  local *human_round = $options{ROUND_FUNCTION};
+
+  return $options{ZERO} if ($bytes==0 && defined $options{ZERO});
+
+  my $block = $options{BLOCK};
+
+  # if a suffix set was not specified, pick a default [**]
+  my @suffixes = $options{SUFFIXES} ? @{$options{SUFFIXES}} : _default_suffixes( ($options{SI} ? 'si_' : '') . $block);
+
+  # WHAT ABOUT NEGATIVE NUMBERS: -1K ?
+  my $sign = '';
+  if ($bytes<0) {
+     $bytes = -$bytes;
+     $sign = '-';
+  }
+
+  my $suffix = $suffixes[0];
+  my $x = $bytes;
+  my $magnitude = 0;
+  if($bytes >= $block) {
+  #  return "$sign$bytes" if $bytes<$block;
+    do {
+      $x /= $block;
+      $magnitude++;
+    } while ( human_round($x, $options{PRECISION}) >= $block );
+    if($magnitude >= (0 + @suffixes)) {
+      carp "number too large (>= $block**$magnitude)" unless ($options{QUIET});
+    }
+    $suffix = $suffixes[$magnitude];
+  }
+  #$x = human_round( $x, $options{PRECISION} );
+
+  $x = _precision_cutoff($x, $options);
+  #reasses encase the precision_cutoff caused the value to cross the block size
+  if($x >= $block) {
+    $x /= $block;
+    $magnitude++;
+    if($magnitude >= (0 + @suffixes)) {
+      carp "number too large (>= $block**$magnitude)" unless ($options{QUIET});
+    }
+    $suffix = $suffixes[$magnitude];
+    $x = _precision_cutoff($x, $options);
+  }
+
+  my $unit = $options{UNIT} || '';
+
+  return $sign . $x . $suffix . $unit;
+
+}
+
+sub _precision_cutoff {
+ my $bytes   = shift;
+ my $options = shift;
+ my %options = %$options;
+ if ( $options{PRECISION_CUTOFF} != -1 and ( length( sprintf( "%d", $bytes ) ) > $options{PRECISION_CUTOFF} ) ) {
+   $bytes = sprintf( "%d", human_round( $bytes, 0 ) );
+ } else {
+   $bytes = sprintf( "%." . $options{PRECISION} . "f", human_round( $bytes, $options{PRECISION} ) );
+ }
+ return $bytes;
+}
+
+sub _parse_bytes {
+  my $human = shift;
+  my $options = shift;
+  my %options = %$options;
+
+  return 0 if( exists $options{ZERO} && ((!defined $options{ZERO} && !defined $human) || (defined $human && $human eq $options{ZERO})) );
+  return undef unless defined $human;
+
+  my %suffix_mult;
+  my %suffix_block;
+  my $m;
+
+  if( $options{SUFFIXES} ) {
+    $m = 1;
+    foreach my $s (@{$options{SUFFIXES}}) {
+      $suffix_mult{$s} = $m;
+      $suffix_block{$s} = $options{BLOCK};
+      $m *= $suffix_block{$s};
+    }
+  } else {
+    if( !defined $options{SI} || $options{SI} == 1 ) {
+      # If SI compatibility has been set BLOCK is ignored as it is infered from the unit
+      $m = 1;
+      foreach my $s (@{$DEFAULT_SUFFIXES{si_1000}}) {
+        $suffix_mult{$s} = $m;
+        $suffix_block{$s} = 1000;
+        $m *= $suffix_block{$s};
+      }
+    
+      $m = 1;
+      foreach my $s (@{$DEFAULT_SUFFIXES{si_1024}}) {
+        $suffix_mult{$s} = $m;
+        $suffix_block{$s} = 1024;
+        $m *= $suffix_block{$s};
+      }
+    }
+
+    # The regular suffixes are only taken into account in default mode without specifically asking for SI compliance
+    if( !defined $options{SI} ) {
+      $m = 1;
+      foreach my $s (_default_suffixes( $options{BLOCK} )) {
+        $suffix_mult{$s} = $m;
+        $suffix_block{$s} = $options{BLOCK};
+        $m *= $suffix_block{$s};
+      }
+    }
+  }
+
+  my ($sign, $k, $unit) = ($human =~ /^\s*(-?)\s*(\d*(?:\.\d*)?)\s*(\D*)$/);
+
+#  print STDERR "S: $sign K: $k U: $unit\n";
+
+
+  my $mult;
+  my $u = $options{UNIT} || '';
+  foreach my $s (keys %suffix_block) {
+    if( $unit =~ /^${s}${u}$/i ) {
+      $mult = ($sign eq '-' ? -1 : 1) * $suffix_mult{$s};
+      last;
+    }
+  }
+
+  if( !defined $mult ) {
+    carp "Could not parse human readable byte value '$human'";
+use Data::Dumper;
+print STDERR Dumper( %suffix_block );
+    return undef;
+  }
+
+  my $bytes = int( $k * $mult );
+
+  return $bytes;
+}
+
+
+# convert byte count (file size) to human readable format
+sub format_bytes {
+  my $bytes = shift;
+  my $options = _parse_args(undef, @_);
+  #use YAML; print Dump $options;
+  return _format_bytes($bytes, $options);
+}
+
+# convert human readable format to byte count (file size)
+sub parse_bytes {
+  my $human = shift;
+  my $options = _parse_args(undef, @_);
+  #use YAML; print Dump $options;
+  return _parse_bytes($human, $options);
+}
+
+### the OO way
+
+# new()
+sub new {
+  my $proto = shift;
+  my $class = ref $proto || $proto;
+  my $opts = _parse_args(undef, @_);
+  return bless $opts, $class;
+}
+
+# set_options()
+sub set_options {
+  my $self = shift;
+  return $self->_parse_args(@_);
+}
+
+# format()
+sub format {
+  my $self = shift;
+  my $bytes = shift;
+  return _format_bytes($bytes, $self);
+}
+
+# parse()
+sub parse {
+  my $self = shift;
+  my $human = shift;
+  return _parse_bytes($human, $self);
+}
+
+# the solution by COG in Filesys::DiskUsage
+# convert size to human readable format
+#sub _convert {
+#  defined (my $size = shift) || return undef;
+#  my $config = {@_};
+#  $config->{human} || return $size;
+#  my $block = $config->{'Human-readable'} ? 1000 : 1024;
+#  my @args = qw/B K M G/;
+#
+#  while (@args && $size > $block) {
+#    shift @args;
+#    $size /= $block;
+#  }
+#
+#  if ($config->{'truncate-readable'} > 0) {
+#    $size = sprintf("%.$config->{'truncate-readable'}f",$size);
+#  }
+#
+#  "$size$args[0]";
+#}
+#
+# not exact: 1024 => 1024B instead of 1K
+# not nicely formatted => 1.00 instead of 1K
+
+1;
+
+__END__
+
+=head1 NAME
+
+Number::Bytes::Human - Convert byte count to human readable format
+
+=head1 SYNOPSIS
+
+  use Number::Bytes::Human qw(format_bytes parse_bytes);
+  $size = format_bytes(0); # '0'
+  $size = format_bytes(2*1024); # '2.0K'
+
+  $size = format_bytes(1_234_890, bs => 1000); # '1.3M'
+  $size = format_bytes(1E9, bs => 1000); # '1.0G'
+
+  my $bytes = parse_bytes('1.0K');   # 1024
+  my $bytes = parse_bytes('1.0KB');  # 1000, SI unit
+  my $bytes = parse_bytes('1.0KiB'); # 1024, SI unit
+
+  # the OO way
+  $human = Number::Bytes::Human->new(bs => 1000, si => 1);
+  $size = $human->format(1E7); # '10MB'
+
+  $bytes = $human->parse('10MB');   # 10*1000*1000
+  $bytes = $human->parse('10MiB');  # 10*1024*1024
+  $bytes = $human->parse('10M');    # Error, no SI unit
+
+  $human->set_options(zero => '-');
+  $size = $human->format(0);    # '-'
+  $bytes = $human->parse('-');  # 0
+
+  $human = Number::Bytes::Human->new(bs => 1000, round_style => 'round', precision => 2);
+  $size = $human->format(10240000); # '10.24MB'
+
+=head1 DESCRIPTION
+
+THIS IS ALPHA SOFTWARE: THE DOCUMENTATION AND THE CODE WILL SUFFER
+CHANGES SOME DAY (THANKS, GOD!).
+
+This module provides a formatter which turns byte counts
+to usual readable format, like '2.0K', '3.1G', '100B'.
+It was inspired in the C<-h> option of Unix
+utilities like C<du>, C<df> and C<ls> for "human-readable" output.
+
+From the FreeBSD man page of C<df>: http://www.freebsd.org/cgi/man.cgi?query=df
+
+  "Human-readable" output.  Use unit suffixes: Byte, Kilobyte,
+  Megabyte, Gigabyte, Terabyte and Petabyte in order to reduce the
+  number of digits to four or fewer using base 2 for sizes.
+
+  byte      B
+  kilobyte  K = 2**10 B = 1024 B
+  megabyte  M = 2**20 B = 1024 * 1024 B
+  gigabyte  G = 2**30 B = 1024 * 1024 * 1024 B
+  terabyte  T = 2**40 B = 1024 * 1024 * 1024 * 1024 B
+
+  petabyte  P = 2**50 B = 1024 * 1024 * 1024 * 1024 * 1024 B
+  exabyte   E = 2**60 B = 1024 * 1024 * 1024 * 1024 * 1024 * 1024 B
+  zettabyte Z = 2**70 B = 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 B
+  yottabyte Y = 2**80 B = 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 B
+
+I have found this link to be quite useful:
+
+  http://www.t1shopper.com/tools/calculate/
+
+If you feel like a hard-drive manufacturer, you can start
+counting bytes by powers of 1000 (instead of the generous 1024).
+Just use C<< bs => 1000 >>.
+
+But if you are a floppy disk manufacturer and want to start
+counting in units of 1024000 (for your "1.44 MB" disks)?
+Then use C<< bs => 1_024_000 >>.
+
+If you feel like a purist academic, you can force the use of
+metric prefixes
+according to the Dec 1998 standard by the IEC. Never mind the units for base 1000
+are C<('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')> and,
+even worse, the ones for base 1024 are
+C<('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')>
+with the horrible names: bytes, kibibytes, mebibytes, etc.
+All you have to do is to use C<< si => 1 >>. Ain't that beautiful
+the SI system? Read about it:
+
+  http://physics.nist.gov/cuu/Units/binary.html
+
+You can try a pure Perl C<"ls -lh">-inspired command with the one-liner, er, two-liner:
+
+  $ perl -MNumber::Bytes::Human=format_bytes \
+         -e 'printf "%5s %s\n", format_bytes(-s), $_ for @ARGV' *
+
+Why to write such a module? Because if people can write such things
+in C, it can be written much easier in Perl and then reused,
+refactored, abused. And then, when it is much improved, some
+brave soul can port it back to C (if only for the warm feeling
+of painful programming).
+
+It is also possible to parse human readable formatted bytes. The 
+automatic format detection recognizes SI units with the blocksizes
+of 1000 and 1024 respectively and additionally the customary K / M / G etc. with
+blocksize 1024. When si => 1 is added to the options only SI units
+are recognized. Explicitly specifying a blocksize changes it
+for all detected units.
+
+=head2 OBJECTS
+
+An alternative to the functional style of this module
+is the OO fashion. This is useful for avoiding the
+unnecessary parsing of the arguments over and over
+if you have to format lots of numbers
+
+
+  for (@sizes) {
+    my $fmt_size = format_bytes($_, @args);
+    ...
+  }
+
+versus
+
+  my $human = Number::Format::Bytes->new(@args);
+  for (@sizes) {
+    my $fmt_size = $human->format($_);
+    ...
+  }
+
+for TODO
+[TODO] MAKE IT JUST A MATTER OF STYLE: memoize _parse_args()
+$seed == undef
+
+=head2 FUNCTIONS
+
+=over 4
+
+=item B<format_bytes>
+
+  $h_size = format_bytes($size, @options);
+
+Turns a byte count (like 1230) to a readable format like '1.3K'.
+You have a bunch of options to play with. See the section
+L</"OPTIONS"> to know the details.
+
+=item B<parse_bytes>
+
+  $size = parse_bytes($h_size, @options);
+
+Turns a human readable byte count into a number of the equivalent bytes.
+
+=back
+
+=head2 METHODS
+
+=over 4
+
+=item B<new>
+
+  $h = Number::Bytes::Human->new(@options);
+
+The constructor. For details on the arguments, see the section
+L</"OPTIONS">.
+
+=item B<format>
+
+  $h_size = $h->format($size);
+
+Turns a byte count (like 1230) to a readable format like '1.3K'.
+The statements
+
+  $h = Number::Bytes::Human->new(@options);
+  $h_size = $h->format($size);
+
+are equivalent to C<$h_size = format_bytes($size, @options)>,
+with only one pass for the option arguments.
+
+=item B<parse>
+
+  $size = $h->parse($h_size)
+
+Turns a human readable byte count into the number of bytes.
+The statements
+
+  $h = Number::Bytes::Human->new(@options);
+  $size = $h->format($h_size);
+
+are equivalent to C<$size = parse_bytes($h_size, @options)>,
+with only one pass for the option arguments.
+
+=item B<set_options>
+
+  $h->set_options(@options);
+
+To alter the options of a C<Number::Bytes::Human> object.
+See L</"OPTIONS">.
+
+=back
+
+=head2 OPTIONS
+
+=over 4
+
+=item BASE
+
+  block | base | block_size | bs => 1000 | 1024 | 1024000
+  base_1024 | block_1024 | 1024 => 1
+  base_1000 | block_1000 | 1000 => 1
+
+The base to be used: 1024 (default), 1000 or 1024000.
+
+Any other value throws an exception.
+
+=item SUFFIXES
+
+  suffixes => 1000 | 1024 | 1024000 | si_1000 | si_1024 | $arrayref
+
+By default, the used suffixes stand for '', 'K', 'M', ...
+for base 1024 and '', 'k', 'M', ... for base 1000
+(which are indeed the usual metric prefixes with implied unit
+as bytes, 'B'). For the weird 1024000 base, suffixes are
+'', 'M', 'T', etc.
+
+=item ZERO
+
+  zero => string | undef
+
+The string C<0> maps to ('0' by default). If C<undef>, the general case is used.
+The string may contain '%S' in which case the suffix for byte is used.
+
+  format_bytes(0, zero => '-') => '-'
+
+=item METRIC SYSTEM
+
+  si => 1
+
+=item ROUND
+
+  round_function => $coderef
+  round_style => 'ceil' | 'floor' | 'round' | 'trunc'
+
+=item TO_S
+
+=item QUIET
+
+  quiet => 1
+
+Suppresses the warnings emitted. Currently, the only case is
+when the number is large than C<$base**(@suffixes+1)>.
+
+=item PRECISION
+
+  precision => <integer>
+
+default = 1
+sets the precicion of digits, only apropreacte for round_style 'round' or if you
+want to accept it in as the second parameter to your custome round_function.
+
+=item PRECISION_CUTOFF
+
+  precision_cutoff => <integer>
+
+default = 1
+when the number of digits exceeds this number causes the precision to be cutoff
+(was default behaviour in 0.07 and below)
+
+=back
+
+=head2 EXPORT
+
+It is alright to import C<format_bytes> and C<parse_bytes>, but nothing is exported by default.
+
+=head1 DIAGNOSTICS
+
+  "unknown round style '$style'";
+
+  "invalid base: $block (should be 1024, 1000 or 1024000)";
+
+  "round function ($args{round_function}) should be a code ref";
+
+  "suffixes ($args{suffixes}) should be 1000, 1024, 1024000 or an array ref";
+
+  "negative numbers are not allowed" (??)
+
+=head1 TO DO
+
+A function C<parse_bytes>
+
+  parse_bytes($str, $options)
+
+which transforms '1k' to 1000, '1K' to 1024, '1MB' to 1E6,
+'1M' to 1024*1024, etc. (like gnu du).
+
+  $str =~ /^\s*(\d*\.?\d*)\s*(\S+)/ # $num $suffix
+
+=head1 SEE ALSO
+
+F<lib/human.c> and F<lib/human.h> in GNU coreutils.
+
+The C<_convert()> solution by COG in Filesys::DiskUsage.
+
+=head1 BUGS
+
+Please report bugs via CPAN RT L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Number-Bytes-Human>
+or L<mailto://bug-Number-Bytes-Human@rt.cpan.org>. I will not be able to close the bug
+as BestPractical ignore my claims that I cannot log in, but I will answer anyway.
+
+=head1 AUTHOR
+
+Adriano R. Ferreira, E<lt>ferreira@cpan.orgE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2005-2007 by Adriano R. Ferreira
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut