applied On Mon, Sep 11, 2017 at 10:41:34AM +0200, Thomas Lamprecht wrote: > We often need to convert between file sizes, for formatting output, > but also code-internal. Some methods expect kilobytes, some gigabytes > and sometimes we need bytes. > > While conversion from smaller to bigger units can be simply done with > a left-shift, the opposite conversion may need more attention - > depending on the used context. > > If we allocate disks this is quite critical. For example, if we need > to allocate a disk with size 1023 bytes using the > PVE::Storage::vdisk_alloc method (which expects kilobytes) a > right shift by 10 (<=> division by 1024) would result in "0", which > obviously fails. > > Thus we round up the converted value if a remainder was lost on the > transformation in this new method. This behaviour is opt-out, to be > on the safe side. > > The method can be used in a clear way, as it gives information about > the source and target unit size, unlike "$var *= 1024", which doesn't > gives direct information at all, if not commented or derived > somewhere from its context. > > For example: > > my $size = convert_unit($value, 'gb' => 'kb'); > is more clear than: > > my $size = $value*1024*1024; > > Signed-off-by: Thomas Lamprecht <t.lampre...@proxmox.com> > --- > > changes v2 -> v3: > * remove returning the remainder, it will not get used yet and feels > not clean. If we want such behavior we can add it easily later and > then, with a real use case, we should be able to create a better > interface then > * die if from or to was not fount in unit hash, normally from/to are > constant not dynamic so this is more convenience for the dev. > > I did not resent the qemu-server part as it was not change in this > iteration > > src/PVE/Tools.pm | 33 +++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm > index 9ddcfda..81662b1 100644 > --- a/src/PVE/Tools.pm > +++ b/src/PVE/Tools.pm > @@ -1617,4 +1617,37 @@ sub encrypt_pw { > return crypt(encode("utf8", $pw), "\$5\$$salt\$"); > } > > +# intended usage: convert_size($val, "kb" => "gb") > +# on reduction (converting to a bigger unit) we round up by default if > +# information got lost. E.g. `convert_size(1023, "b" => "kb")` returns 1 > +# use $no_round_up to switch this off, above example would then return 0 > +sub convert_size { > + my ($value, $from, $to, $no_round_up) = @_; > + > + my $units = { > + b => 0, > + kb => 1, > + mb => 2, > + gb => 3, > + tb => 4, > + pb => 5, > + }; > + > + $from = lc($from); $to = lc($to); > + die "unknown 'from' and/or 'to' units ($from => $to)" > + if !(defined($units->{$from}) && defined($units->{$to})); > + > + my $shift_amount = $units->{$from} - $units->{$to}; > + > + if ($shift_amount > 0) { > + $value <<= ($shift_amount * 10); > + } elsif ($shift_amount < 0) { > + my $remainder = ($value & (1 << abs($shift_amount)*10) - 1); > + $value >>= abs($shift_amount) * 10; > + $value++ if $remainder && !$no_round_up; > + } > + > + return $value; > +} > + > 1; > -- > 2.11.0
_______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel