diff --git a/README.md b/README.md index 1efaa90..0450138 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ That means: ### Parsing a string ```ruby Filesize.from("1 GiB") -# => #/^([\d,.]+)?\s?(?:([kmgtpezy])i)?b$/i, :multiplier=>1024, :presuffix=>"i"}> +# => #/^(-?)([\d,.]+)?[[:space:]]?(?:([kmgtpezy])i)?b?$/i, :multiplier=>1024, :prefixes=>["Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"], :presuffix=>"i"}> ``` ### Converting filesizes diff --git a/lib/filesize.rb b/lib/filesize.rb index 745ab06..c72aa1f 100644 --- a/lib/filesize.rb +++ b/lib/filesize.rb @@ -13,14 +13,14 @@ class Filesize # Set of rules describing file sizes according to SI units. SI = { - :regexp => /^([\d,.]+)?[[:space:]]?([kmgtpezy]?)b?$/i, + :regexp => /^(-?)([\d,.]+)?[[:space:]]?([kmgtpezy]?)b?$/i, :multiplier => 1000, :prefixes => TYPE_PREFIXES[:SI], :presuffix => '' # deprecated } # Set of rules describing file sizes according to binary units. BINARY = { - :regexp => /^([\d,.]+)?[[:space:]]?(?:([kmgtpezy])i)?b?$/i, + :regexp => /^(-?)([\d,.]+)?[[:space:]]?(?:([kmgtpezy])i)?b?$/i, :multiplier => 1024, :prefixes => TYPE_PREFIXES[:BINARY], :presuffix => 'i' # deprecated @@ -71,14 +71,14 @@ def to_s(unit = 'B') # @return [String] # @see #to_s def pretty - size = @bytes + size = @bytes.abs if size < @type[:multiplier] - unit = "B" + unit = 'B' else pos = (Math.log(size) / Math.log(@type[:multiplier])).floor pos = @type[:prefixes].size-1 if pos > @type[:prefixes].size - 1 - unit = @type[:prefixes][pos-1] + "B" + unit = @type[:prefixes][pos-1] + 'B' end to_s(unit) @@ -151,10 +151,11 @@ def parse(string) end } - prefix = $2 || '' - size = ($1 || 0).to_f + sign = $1 == '' ? 1 : -1 + prefix = $3 || '' + size = ($2 || 0).to_f * sign - return { :prefix => prefix, :size => size, :type => type} + return { :prefix => prefix, :size => size, :type => type } end end diff --git a/spec/lib/filesize_spec.rb b/spec/lib/filesize_spec.rb index 711bd8f..54178a6 100644 --- a/spec/lib/filesize_spec.rb +++ b/spec/lib/filesize_spec.rb @@ -42,6 +42,18 @@ it 'parses megabytes without b suffix' do expect(Filesize.from('1 M').to).to eq 1000 * 1000 end + + it 'parses negative kilobytes' do + expect(Filesize.from('-1 kB').to).to eq -1000 + end + + it 'parses negative megabytes' do + expect(Filesize.from('-1 MB').to).to eq -1000 * 1000 + end + + it 'parses negative megabytes without b suffix' do + expect(Filesize.from('-1 M').to).to eq -1000 * 1000 + end end context 'BINARY units' do @@ -56,6 +68,18 @@ it 'parses mebibytes without b suffix' do expect(Filesize.from('1 Mi').to).to eq 1024 * 1024 end + + it 'parses negative kilobytes' do + expect(Filesize.from('-1 KiB').to).to eq -1024 + end + + it 'parses negative megabytes' do + expect(Filesize.from('-1 MiB').to).to eq -1024 * 1024 + end + + it 'parses negative mebibytes without b suffix' do + expect(Filesize.from('-1 Mi').to).to eq -1024 * 1024 + end end end @@ -105,12 +129,24 @@ end describe '#pretty' do - it 'returns the number of the most matching prefix with its unit (BINARY default)' do - expect(Filesize.new(1024).pretty).to eq '1.00 KiB' + context 'BINARY units (default)' do + it 'returns the number of the most matching prefix with its unit' do + expect(Filesize.new(1024).pretty).to eq '1.00 KiB' + end + + it 'returns the negative number of the most matching prefix with its unit' do + expect(Filesize.new(-1024).pretty).to eq '-1.00 KiB' + end end - it 'returns the number of the most matching prefix with its unit (SI)' do - expect(Filesize.new(1000, Filesize::SI).pretty).to eq '1.00 kB' + context 'SI units' do + it 'returns the number of the most matching prefix with its unit' do + expect(Filesize.new(1000, Filesize::SI).pretty).to eq '1.00 kB' + end + + it 'returns the negative number of the most matching prefix with its unit' do + expect(Filesize.new(-1000, Filesize::SI).pretty).to eq '-1.00 kB' + end end end