Class: ByteSize
- Inherits:
-
Object
- Object
- ByteSize
- Includes:
- Comparable
- Defined in:
- lib/bytesize.rb,
lib/bytesize/version.rb,
lib/bytesize/activerecord.rb
Overview
This class is used to represent a size in bytes.
It uses the SI standard unit symbols: kB, MB, GB, TB, PB, EB, ZB, YB.
For a version that uses the IEC standard unit symbols, see IECByteSize[IECByteSize.html].
Examples of use
ByteSize.new( 4127 ) #=> (4.13 kB)
ByteSize.new( "22 GB" ) #=> (22 GB)
ByteSize.new( "22 GiB" ) #=> (23.62 GB)
ByteSize.bytes( 42 ) #=> (42 bytes)
ByteSize.kb( 42 ) #=> (42 kB)
ByteSize.mb( 42 ) #=> (42 MB)
ByteSize.gb( 42 ) #=> (42 GB)
ByteSize.tb( 42 ) #=> (42 TB)
ByteSize.pb( 42 ) #=> (42 PB)
ByteSize.eb( 42 ) #=> (42 EB)
ByteSize.zb( 42 ) #=> (42 ZB)
ByteSize.yb( 42 ) #=> (42 YB)
Conversion of values:
ByteSize.gb( 100 ).to_gib #=> 93.13225746154785
ByteSize.gib( 2.42 ).to_mib #=> 2478.079999923706
With numeric convenience methods:
require 'bytesize/unit'
100.gb.to_gib #=> 93.13225746154785
2.42.gib.to_mib #=> 2478.079999923706
Direct Known Subclasses
Defined Under Namespace
Classes: ActiveRecordType
Constant Summary collapse
- SI_BASE =
:stopdoc:
1000- SI_ORDERS_OF_MAGNITUDE =
{ bytes: 1, kB: SI_BASE, MB: SI_BASE**2, GB: SI_BASE**3, TB: SI_BASE**4, PB: SI_BASE**5, EB: SI_BASE**6, ZB: SI_BASE**7, YB: SI_BASE**8 }.freeze
- IEC_BASE =
1024- IEC_ORDERS_OF_MAGNITUDE =
{ bytes: 1, KiB: IEC_BASE, MiB: IEC_BASE**2, GiB: IEC_BASE**3, TiB: IEC_BASE**4, PiB: IEC_BASE**5, EiB: IEC_BASE**6, ZiB: IEC_BASE**7, YiB: IEC_BASE**8 }.freeze
- UNIT_SYMBOLS =
SI_ORDERS_OF_MAGNITUDE.merge(IEC_ORDERS_OF_MAGNITUDE)
- ORDERS_OF_MAGNITUDE =
SI_ORDERS_OF_MAGNITUDE- BYTES_REGEX =
:stopdoc:
/\A\s*(\-?[0-9]+)\s*(bytes)?\s*\z/.freeze
- SI_REGEX =
/\A\s*(\-?[0-9]+(\.[0-9]+)?)\s*(#{ SI_ORDERS_OF_MAGNITUDE.keys.reject{|k| k == :bytes }.join('|') })\s*\z/i.freeze
- IEC_REGEX =
/\A\s*(\-?[0-9]+(\.[0-9]+)?)\s*(#{ IEC_ORDERS_OF_MAGNITUDE.keys.reject{|k| k == :bytes }.join('|') })\s*\z/i.freeze
- VERSION =
"0.1.0".freeze
Instance Attribute Summary collapse
-
#bytes ⇒ Object
(also: #to_bytes)
:stopdoc:.
Class Method Summary collapse
-
.bytes(b) ⇒ Object
:call-seq: ByteSize.bytes( n ) -> bytesize.
-
.new(val) ⇒ Object
:stopdoc:.
-
.parse(val) ⇒ Object
call-seq: ByteSize.parse( string ) -> bytesize.
Instance Method Summary collapse
-
#%(val) ⇒ Object
:call-seq: bytesize % val -> bytesize.
-
#*(val) ⇒ Object
:call-seq: bytesize * val -> bytesize.
-
#**(pow) ⇒ Object
:call-seq: bytesize ** pow -> bytesize.
-
#+(val) ⇒ Object
:call-seq: bytesize + val -> bytesize.
-
#+@ ⇒ Object
:call-seq: +bytesize -> bytesize.
-
#-(val) ⇒ Object
:call-seq: bytesize - val -> bytesize.
-
#-@ ⇒ Object
:call-seq: -bytesize -> bytesize.
-
#/(val) ⇒ Object
:call-seq: bytesize / val -> bytesize or float.
-
#<(other) ⇒ Object
:call-seq: bytesize < val -> true or false.
-
#<=(other) ⇒ Object
:call-seq: bytesize <= val -> true or false.
-
#<=>(other) ⇒ Object
:call-seq: bytesize <=> other -> -1, 0, 1, or nil.
-
#==(other) ⇒ Object
(also: #===)
:call-seq: bytesize == other -> true or false.
-
#>(other) ⇒ Object
:call-seq: bytesize > val -> true or false.
-
#>=(other) ⇒ Object
:call-seq: bytesize >= val -> true or false.
-
#coerce(other) ⇒ Object
:stopdoc:.
-
#eql?(other) ⇒ Boolean
:call-seq: eql?( other_bytesize ) -> true or false.
-
#hash ⇒ Object
:stopdoc:.
-
#initialize(bytes) ⇒ ByteSize
constructor
call-seq: new( integer ) new( string ).
-
#inspect ⇒ Object
:call-seq: inspect -> string.
-
#negative? ⇒ Boolean
:call-seq: negative? -> true or false.
-
#positive? ⇒ Boolean
:call-seq: positive? -> true or false.
-
#to_i ⇒ Object
:call-seq: to_i -> integer.
-
#to_iec ⇒ Object
:call-seq: to_iec -> iecbytesize.
-
#to_s(decimal_places = nil) ⇒ Object
:call-seq: to_s -> string to_s( decimal_places ) -> string.
-
#to_si ⇒ Object
:call-seq: to_si -> bytesize.
-
#zero? ⇒ Boolean
:call-seq: zero? -> true or false.
Constructor Details
#initialize(bytes) ⇒ ByteSize
373 374 375 376 377 |
# File 'lib/bytesize.rb', line 373 def initialize( bytes ) raise( TypeError, "expected #{Integer}, got #{bytes.class}" ) unless bytes.is_a?(Integer) @bytes = bytes freeze end |
Instance Attribute Details
#bytes ⇒ Object Also known as: to_bytes
:stopdoc:
875 876 877 |
# File 'lib/bytesize.rb', line 875 def bytes @bytes end |
Class Method Details
.bytes(b) ⇒ Object
138 139 140 141 |
# File 'lib/bytesize.rb', line 138 def self.bytes( b ) raise( TypeError, "expected #{Numeric}, got #{b.class}" ) unless b.is_a?(Numeric) self.new( b.round ) end |
.new(val) ⇒ Object
:stopdoc:
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
# File 'lib/bytesize.rb', line 332 def self.new( val ) if val.class == self super( val.bytes ) else case val when Integer super( val ) when ByteSize super( val.bytes ) when String if m = val.match(BYTES_REGEX) super( m[1].to_i ) elsif m = val.match(SI_REGEX) self.send( m[3].downcase.to_sym, m[2].nil? ? m[1].to_i : m[1].to_f ) elsif m = val.match(IEC_REGEX) self.send( m[3].downcase.to_sym, m[2].nil? ? m[1].to_i : m[1].to_f ) else raise( ArgumentError, "invalid #{self} string: #{val.inspect}" ) end else raise( TypeError, "no implicit conversion of #{val.class} into #{self}" ) end end end |
.parse(val) ⇒ Object
call-seq:
ByteSize.parse( string ) -> bytesize
Parses a String into either a ByteSize or IECByteSize depending on it’s unit symbol.
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
# File 'lib/bytesize.rb', line 312 def self.parse( val ) case val when String if m = val.match(BYTES_REGEX) ByteSize.new( m[1].to_i ) elsif m = val.match(SI_REGEX) ByteSize.send( m[3].downcase.to_sym, m[2].nil? ? m[1].to_i : m[1].to_f ) elsif m = val.match(IEC_REGEX) IECByteSize.send( m[3].downcase.to_sym, m[2].nil? ? m[1].to_i : m[1].to_f ) else raise( ArgumentError, "invalid #{ByteSize} or #{IECByteSize} string: #{val.inspect}" ) end else raise( TypeError, "expected #{String}, got #{str.class}" ) end end |
Instance Method Details
#%(val) ⇒ Object
637 638 639 640 641 642 643 644 645 646 647 648 649 |
# File 'lib/bytesize.rb', line 637 def %( val ) case val when Numeric self.class.new(( bytes % val ).round) when ByteSize self.class.new( bytes % val.bytes ) else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end |
#*(val) ⇒ Object
662 663 664 665 666 667 668 669 670 671 672 673 674 |
# File 'lib/bytesize.rb', line 662 def *( val ) case val when Numeric self.class.new(( bytes * val ).round) when ByteSize raise( TypeError, "cannot multiply #{ByteSize} with #{val.class}" ) else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end |
#**(pow) ⇒ Object
687 688 689 690 691 692 693 694 695 696 697 698 699 |
# File 'lib/bytesize.rb', line 687 def **( pow ) case pow when Numeric self.class.new(( bytes ** pow ).round) when ByteSize raise( TypeError, "cannot raise #{ByteSize} to a power of #{pow.class}" ) else raise( TypeError, "#{pow.class} can't be coerced into #{self.class}" ) end end |
#+(val) ⇒ Object
711 712 713 714 715 716 717 718 719 720 721 722 723 |
# File 'lib/bytesize.rb', line 711 def +( val ) case val when Numeric self.class.new(( bytes + val ).round) when ByteSize self.class.new( bytes + val.bytes ) else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end |
#+@ ⇒ Object
:call-seq:
+bytesize -> bytesize
Unary Plus — Returns the receiver’s value.
733 734 735 |
# File 'lib/bytesize.rb', line 733 def +@ self end |
#-(val) ⇒ Object
747 748 749 750 751 752 753 754 755 756 757 758 759 |
# File 'lib/bytesize.rb', line 747 def -( val ) case val when Numeric self.class.new(( bytes - val ).round) when ByteSize self.class.new( bytes - val.bytes ) else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end |
#-@ ⇒ Object
:call-seq:
-bytesize -> bytesize
Unary Minus — Returns the receiver’s value, negated.
769 770 771 |
# File 'lib/bytesize.rb', line 769 def -@ self.class.new( 0 - bytes ) end |
#/(val) ⇒ Object
786 787 788 789 790 791 792 793 794 795 796 797 798 |
# File 'lib/bytesize.rb', line 786 def /( val ) case val when Numeric self.class.new(( bytes / val ).round) when ByteSize bytes.to_f / val.bytes.to_f else raise( TypeError, "#{val.class} can't be coerced into #{self.class}" ) end end |
#<(other) ⇒ Object
:call-seq:
bytesize < val -> true or false
Returns true if the value of bytesize is less than that of val.
547 548 549 550 551 552 553 554 555 556 557 558 559 |
# File 'lib/bytesize.rb', line 547 def <( other ) case other when Numeric bytes < other when ByteSize bytes < other.bytes else raise( ArgumentError, "comparison of #{self.class} with #{other.inspect} failed" ) end end |
#<=(other) ⇒ Object
:call-seq:
bytesize <= val -> true or false
Returns true if the value of bytesize is less than or equal to that of val.
569 570 571 572 573 574 575 576 577 578 579 580 581 |
# File 'lib/bytesize.rb', line 569 def <=( other ) case other when Numeric bytes <= other when ByteSize bytes <= other.bytes else raise( ArgumentError, "comparison of #{self.class} with #{other.inspect} failed" ) end end |
#<=>(other) ⇒ Object
:call-seq:
bytesize <=> other -> -1, 0, 1, or nil
Compares bytesize to other and returns 0 if they are equal, -1 if bytesize is less than other, or 1 if bytesize is greater than other.
Returns nil if the two values are incomparable.
812 813 814 815 816 817 818 819 820 821 822 823 824 |
# File 'lib/bytesize.rb', line 812 def <=>( other ) case other when Numeric bytes <=> other when ByteSize bytes <=> other.bytes else nil end end |
#==(other) ⇒ Object Also known as: ===
:call-seq:
bytesize == other -> true or false
Returns true if bytesize is equal to other.
If other is not an instance of ByteSize an attempt will be made to convert it to one.
836 837 838 839 840 841 842 843 844 845 846 847 848 |
# File 'lib/bytesize.rb', line 836 def ==( other ) case other when Numeric bytes == other when ByteSize bytes == other.bytes else false end end |
#>(other) ⇒ Object
:call-seq:
bytesize > val -> true or false
Returns true if the value of bytesize is greater than that of val.
591 592 593 594 595 596 597 598 599 600 601 602 603 |
# File 'lib/bytesize.rb', line 591 def >( other ) case other when Numeric bytes > other when ByteSize bytes > other.bytes else raise( ArgumentError, "comparison of #{self.class} with #{other.inspect} failed" ) end end |
#>=(other) ⇒ Object
:call-seq:
bytesize >= val -> true or false
Returns true if the value of bytesize is greater than or equal to that of val.
613 614 615 616 617 618 619 620 621 622 623 624 625 |
# File 'lib/bytesize.rb', line 613 def >=( other ) case other when Numeric bytes >= other when ByteSize bytes >= other.bytes else raise( ArgumentError, "comparison of #{self.class} with #{other.inspect} failed" ) end end |
#coerce(other) ⇒ Object
:stopdoc:
881 882 883 884 885 886 887 888 889 890 891 |
# File 'lib/bytesize.rb', line 881 def coerce( other ) if Numeric [ other, self.to_i ] else begin [ self.class.new(other), self ] rescue raise( TypeError, "#{other.class} can't be coerced into #{self.class}" ) end end end |
#eql?(other) ⇒ Boolean
:call-seq:
eql?( other_bytesize ) -> true or false
Returns true if the ByteSize is equal to other_bytesize.
902 903 904 |
# File 'lib/bytesize.rb', line 902 def eql?( other ) other.class == self.class && other.bytes == bytes end |
#hash ⇒ Object
:stopdoc:
909 910 911 |
# File 'lib/bytesize.rb', line 909 def hash bytes.hash end |
#inspect ⇒ Object
926 927 928 |
# File 'lib/bytesize.rb', line 926 def inspect sprintf( '(%s)', to_s ) end |
#negative? ⇒ Boolean
938 939 940 |
# File 'lib/bytesize.rb', line 938 def negative? bytes < 0 end |
#positive? ⇒ Boolean
950 951 952 |
# File 'lib/bytesize.rb', line 950 def positive? bytes > 0 end |
#to_i ⇒ Object
976 977 978 |
# File 'lib/bytesize.rb', line 976 def to_i bytes.to_i end |
#to_iec ⇒ Object
:call-seq:
to_iec -> iecbytesize
Returns the size as an instance of IECByteSize.
If called on an instance of IECByteSize it returns self.
990 991 992 |
# File 'lib/bytesize.rb', line 990 def to_iec self.class == IECByteSize ? self : IECByteSize.new(self.to_i) end |
#to_s(decimal_places = nil) ⇒ Object
:call-seq:
to_s -> string
to_s( decimal_places ) -> string
Format this ByteSize as a String.
The second form formats it with exactly decimal_places decimal places.
Example:
ByteSize.bytes(3000000000000).to_s #=> "3 TB"
ByteSize.bytes(2460000000000).to_s #=> "2.46 TB"
ByteSize.bytes(3000000000000).to_s(2) #=> "3.00 TB"
ByteSize.bytes(1234567890000).to_s(2) #=> "1.23 TB"
ByteSize.bytes(1234567890000).to_s(4) #=> "1.2346 TB"
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
# File 'lib/bytesize.rb', line 1014 def to_s( decimal_places=nil ) unless decimal_places.nil? raise( TypeError, "expected #{Integer}, got #{decimal_places.class}" ) unless decimal_places.is_a?(Integer) raise( RangeError, "decimal places cannot be negative" ) unless decimal_places >= 0 end b = bytes.abs scale = self.class::ORDERS_OF_MAGNITUDE.sort{|(ak,av),(bk,bv)| av <=> bv } if b == 0 unit = scale.first else unit = scale.find_index{|k,v| v > b } if unit.nil? unit = scale.last else unit = scale[unit-1] end end if decimal_places.nil? sprintf( negative? ? '-%g %s' : '%g %s', ((b/Float(unit.last))*100).round/100.0, unit.first.to_s ) else sprintf( negative? ? "-%.0#{decimal_places}f %s" : "%.0#{decimal_places}f %s", b / Float(unit.last), unit.first.to_s ) end end |
#to_si ⇒ Object
1052 1053 1054 |
# File 'lib/bytesize.rb', line 1052 def to_si self.class == ByteSize ? self : ByteSize.new(self.to_i) end |
#zero? ⇒ Boolean
1064 1065 1066 |
# File 'lib/bytesize.rb', line 1064 def zero? bytes == 0 end |