Module: Tins::Unit

Defined in:
lib/tins/unit.rb

Overview

A module for parsing and formatting unit specifications with support for various prefix types and unit formats.

Examples:

Basic usage

Tins::Unit.parse('1.5 GB').round # => 1610612736
Tins::Unit.format(1610612736, unit: 'B') # => "1.500000 GB"
Tins::Unit.parse('1000 mb', prefix: 1000).round # => 1000000000

Defined Under Namespace

Classes: FormatParser, ParserError, Prefix, UnitParser

Constant Summary collapse

PREFIX_LC =

An array of prefix objects for lowercase decimal prefixes (k, M, G…) based on 1000-step increments.

[
  '', 'k', 'm', 'g', 't', 'p', 'e', 'z', 'y',
].each_with_index.map { |n, i| Prefix.new(n.freeze, 1000, 1000 ** i, false) }.freeze
PREFIX_UC =

An array of prefix objects for uppercase binary prefixes (K, M, G…) based on 1024-step increments.

[
  '', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y',
].each_with_index.map { |n, i| Prefix.new(n.freeze, 1024, 1024 ** i, false) }.freeze
PREFIX_F =

An array of prefix objects for fractional prefixes (m, µ, n…) based on 1000-step decrements.

[
  '', 'm', 'µ', 'n', 'p', 'f', 'a', 'z', 'y',
].each_with_index.map { |n, i| Prefix.new(n.freeze, 1000, 1000 ** -i, true) }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.format(value, format: '%f %U', prefix: 1024, unit: ?b) ⇒ Object

Format a value using unit prefixes and a specified format template.

This method takes a numerical value and formats it according to the given format string, inserting the appropriate unit prefix based on the specified prefix type and unit identifier.

Parameters:

  • value (Numeric)

    the numerical value to format

  • format (String) (defaults to: '%f %U')

    the format template to use for output, default is ‘%f %U’

  • prefix (Object) (defaults to: 1024)

    the prefix configuration to use, default is 1024 (binary prefixes)

  • unit (String, Symbol) (defaults to: ?b)

    the unit identifier to append, default is ?b (bytes)



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/tins/unit.rb', line 73

def format(value, format: '%f %U', prefix: 1024, unit: ?b)
  prefixes = prefixes(prefix)
  first_prefix = prefixes.first or
    raise ArgumentError, 'a non-empty array of prefixes is required'
  if value.zero?
    result = format.sub('%U', unit)
    result %= value
  else
    prefix = prefixes[
      (first_prefix.fraction ? -1 : 1) * Math.log(value.abs) / Math.log(first_prefix.step)
    ]
    result = format.sub('%U', "#{prefix.name}#{unit}")
    result %= (value / prefix.multiplier.to_f)
  end
end

.parse(string, format: '%f %U', unit: ?b, prefix: nil) ⇒ Object

Parse the string using the specified format and unit information

This method takes a string and parses it according to a given format template, extracting numerical values and their associated units. It supports various prefix types and unit specifications for flexible parsing.

Parameters:

  • string (String)

    the input string to parse

  • format (String) (defaults to: '%f %U')

    the format template to use for parsing (default: ‘%f %U’)

  • unit (String, Symbol) (defaults to: ?b)

    the unit identifier to use (default: ?b)

  • prefix (Object) (defaults to: nil)

    the prefix configuration to use (default: nil)

Returns:

  • (Object)

    the parsed result based on the format and unit specifications



301
302
303
304
# File 'lib/tins/unit.rb', line 301

def parse(string, format: '%f %U', unit: ?b, prefix: nil)
  prefixes = prefixes(prefix)
  FormatParser.new(format, UnitParser.new(string, unit, prefixes)).parse
end

.parse?(string, **options) ⇒ Object?

The parse? method attempts to parse a string using the specified options and returns nil if parsing fails.

Parameters:

  • string (String)

    the string to parse

  • options (Hash)

    the options to pass to the parse method

Returns:

  • (Object, nil)

    the parsed result or nil if parsing fails



312
313
314
315
316
# File 'lib/tins/unit.rb', line 312

def parse?(string, **options)
  parse(string, **options)
rescue ParserError
  nil
end

.prefixes(identifier) ⇒ Array

The prefixes method returns an array of prefix objects based on the given identifier.

This method maps different identifier symbols and values to predefined arrays of prefix objects, allowing for flexible configuration of unit prefixes.

Parameters:

  • identifier (Symbol, Integer, Array)

    the identifier specifying which prefix set to return

Returns:

  • (Array)

    an array of prefix objects corresponding to the identifier



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/tins/unit.rb', line 50

def prefixes(identifier)
  case identifier
  when :uppercase, :uc, 1024
    PREFIX_UC
  when :lowercase, :lc, 1000
    PREFIX_LC
  when :fraction, :f, 0.001
    PREFIX_F
  when Array
    identifier
  end
end

Instance Method Details

#format(value, format: '%f %U', prefix: 1024, unit: ?b) ⇒ Object (private)

Format a value using unit prefixes and a specified format template.

This method takes a numerical value and formats it according to the given format string, inserting the appropriate unit prefix based on the specified prefix type and unit identifier.

Parameters:

  • value (Numeric)

    the numerical value to format

  • format (String) (defaults to: '%f %U')

    the format template to use for output, default is ‘%f %U’

  • prefix (Object) (defaults to: 1024)

    the prefix configuration to use, default is 1024 (binary prefixes)

  • unit (String, Symbol) (defaults to: ?b)

    the unit identifier to append, default is ?b (bytes)



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/tins/unit.rb', line 73

def format(value, format: '%f %U', prefix: 1024, unit: ?b)
  prefixes = prefixes(prefix)
  first_prefix = prefixes.first or
    raise ArgumentError, 'a non-empty array of prefixes is required'
  if value.zero?
    result = format.sub('%U', unit)
    result %= value
  else
    prefix = prefixes[
      (first_prefix.fraction ? -1 : 1) * Math.log(value.abs) / Math.log(first_prefix.step)
    ]
    result = format.sub('%U', "#{prefix.name}#{unit}")
    result %= (value / prefix.multiplier.to_f)
  end
end

#parse(string, format: '%f %U', unit: ?b, prefix: nil) ⇒ Object (private)

Parse the string using the specified format and unit information

This method takes a string and parses it according to a given format template, extracting numerical values and their associated units. It supports various prefix types and unit specifications for flexible parsing.

Parameters:

  • string (String)

    the input string to parse

  • format (String) (defaults to: '%f %U')

    the format template to use for parsing (default: ‘%f %U’)

  • unit (String, Symbol) (defaults to: ?b)

    the unit identifier to use (default: ?b)

  • prefix (Object) (defaults to: nil)

    the prefix configuration to use (default: nil)

Returns:

  • (Object)

    the parsed result based on the format and unit specifications



301
302
303
304
# File 'lib/tins/unit.rb', line 301

def parse(string, format: '%f %U', unit: ?b, prefix: nil)
  prefixes = prefixes(prefix)
  FormatParser.new(format, UnitParser.new(string, unit, prefixes)).parse
end

#parse?(string, **options) ⇒ Object? (private)

The parse? method attempts to parse a string using the specified options and returns nil if parsing fails.

Parameters:

  • string (String)

    the string to parse

  • options (Hash)

    the options to pass to the parse method

Returns:

  • (Object, nil)

    the parsed result or nil if parsing fails



312
313
314
315
316
# File 'lib/tins/unit.rb', line 312

def parse?(string, **options)
  parse(string, **options)
rescue ParserError
  nil
end

#prefixes(identifier) ⇒ Array (private)

The prefixes method returns an array of prefix objects based on the given identifier.

This method maps different identifier symbols and values to predefined arrays of prefix objects, allowing for flexible configuration of unit prefixes.

Parameters:

  • identifier (Symbol, Integer, Array)

    the identifier specifying which prefix set to return

Returns:

  • (Array)

    an array of prefix objects corresponding to the identifier



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/tins/unit.rb', line 50

def prefixes(identifier)
  case identifier
  when :uppercase, :uc, 1024
    PREFIX_UC
  when :lowercase, :lc, 1000
    PREFIX_LC
  when :fraction, :f, 0.001
    PREFIX_F
  when Array
    identifier
  end
end