class BaseX

Constants

Base16
Base16L

Base 16

Base16U
Base256

Binary string encoding; turn binary strings into Bignums and back

Base30L

Base 30, in case the number could change case no “u” following Crockford’s probabilistic fear of accidental obscenity (I caluclate the probability of obscenity, with “u”, is about 1 in 2^13 for any given random 3-letter string (about 1 in 8000); when encoding 128bit tokens, after generating about 225 random tokens you have a 50% chance of having produced an “obscene token”.)

Base30U
Base31L

Base 31, in case the number could change case

Base31U
Base58
Base62
Base62DLU
Base62DUL

Base62; digits, upper, lower

Base62LDU
Base62LUD
Base62UDL
Base62ULD
Binary

Binary

BitcoinBase58

Base58 schemes

CrockfordBase32
EXAMPLE_TOKEN
FlickrBase58
GMPBase58
Hex
Hexadecimal
NewBase60

NewBase60, has an underscore as per tantek.pbworks.com/w/page/19402946/NewBase60

RFC4648Base32

Base 32 schemes

URLBase64

URL Base 64

VERSION
Z85

ZeroMQ Base 85 Process your data back and forth between 4-byte and 5-byte chunks and you’ll be compatible with the Z85 standard

Attributes

base[R]
numerals[R]

Public Class Methods

base(n) click to toggle source
# File lib/base_x.rb, line 42
def self.base(n)
  n.between?(2, 62) or raise ArgumentError.new("Base #{n} is not valid; base must be at least 2 and at most 62")
  digits_uppercase_lowercase = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  new(digits_uppercase_lowercase[0...n])
end
bases() click to toggle source

Outputs an array of [base name, base size, example, and numerals] for all built-in bases

# File lib/base_x.rb, line 49
def self.bases
  constants
    .map     { |const_name| [const_name, const_get(const_name)] }
    .select  { |const_name, base| base.is_a?(BaseX) }
    .sort_by { |const_name, base| [base.base, const_name.to_s] }
    .map do |const_name, base|
      [const_name.to_s, base.base, base.encode(EXAMPLE_TOKEN), base.numerals]
    end
end
bases_table() click to toggle source
# File lib/base_x.rb, line 59
def self.bases_table
  bases.map do |name, base_size, example, numerals|
    example = example[0...21] + "…" if example.size > 22
    [
      name,
      base_size,
      example.inspect.include?("\\")  ? example.inspect  : example,
      numerals.inspect.include?("\\") ? numerals.inspect : numerals,
    ]
  end.map do |array|
    "%-15s %-3s %-22s %s" % array
  end.join("\n")
end
decode(encoded, opts) click to toggle source
# File lib/base_x.rb, line 36
def self.decode(encoded, opts)
  opts[:numerals].respond_to?(:index) or
    raise ArgumentError.new("A string of numerals must be provided, e.g. BaseX.encode(\"bcaffag\", numerals: \"abcdefg\")")
  new(opts[:numerals]).decode(encoded)
end
encode(string, opts) click to toggle source
# File lib/base_x.rb, line 30
def self.encode(string, opts)
  opts[:numerals].respond_to?(:index) or
    raise ArgumentError.new("A string of numerals must be provided, e.g. BaseX.encode(\"Hello World\", numerals: \"abcdefg\")")
  new(opts[:numerals]).encode(string)
end
integer_to_string(int, opts) click to toggle source
# File lib/base_x.rb, line 24
def self.integer_to_string(int, opts)
  opts[:numerals].respond_to?(:index) or
    raise ArgumentError.new("A string of numerals must be provided, e.g. BaseX.integer_to_string(123, numerals: \"abcdefg\")")
  new(opts[:numerals]).integer_to_string(int)
end
new(numerals) click to toggle source
# File lib/base_x.rb, line 80
def initialize(numerals)
  numerals.chars.size > 1 or
    raise ArgumentError.new("Need at least two numerals to express numbers! Numeral given: #{numerals.inspect}") 
  numerals.chars.size == numerals.chars.uniq.size or
    raise ArgumentError.new("Duplicate characters found in numerals definition: #{numerals.inspect}") 
  @numerals = numerals
  @base     = numerals.size
end
print_bases() click to toggle source
string_to_integer(string, opts) click to toggle source
# File lib/base_x.rb, line 18
def self.string_to_integer(string, opts)
  opts[:numerals].respond_to?(:index) or
    raise ArgumentError.new("A string of numerals must be provided, e.g. BaseX.string_to_integer(\"bcde\", numerals: \"abcdefg\")")
  new(opts[:numerals]).string_to_integer(string)
end

Public Instance Methods

decode(encoded) click to toggle source
# File lib/base_x.rb, line 126
def decode(encoded)
  return "" if encoded.size == 0
  int = string_to_integer(encoded)
  decoded = Base256.integer_to_string(int)
  decoded_number_size = 256**(decoded.size)
  encoded_number_size = base**(encoded.size)

  # encoded_number_size / base < decoded_number_size <= encoded_number_size
  while decoded_number_size <= encoded_number_size / base
    decoded = "\x00" + decoded
    decoded_number_size *= 256
  end

  decoded
end
encode(string) click to toggle source
# File lib/base_x.rb, line 111
def encode(string)
  return "" if string.size == 0
  int = string.each_byte.reduce(0) { |int, byte| int *= 256; int + byte }
  encoded = integer_to_string(int)
  string_number_size = 256**(string.size)
  encoded_number_size = base**(encoded.size)

  while encoded_number_size < string_number_size
    encoded = @numerals[0] + encoded
    encoded_number_size *= base
  end

  encoded
end
integer_to_string(int) click to toggle source
# File lib/base_x.rb, line 100
def integer_to_string(int)
  return @numerals[0] if int == 0
  string = ""
  while int > 0
    char = @numerals[int % base]
    string << char
    int /= base
  end
  string.reverse
end
string_to_integer(string) click to toggle source
# File lib/base_x.rb, line 89
def string_to_integer(string)
  raise EmptyString.new unless string.size > 0
  integer = 0
  string.each_char do |char|
    integer *= base
    numeral_value = @numerals.index(char) or raise InvalidNumeral.new(char)
    integer += numeral_value
  end
  integer
end