Class: BaseConvert::Digits

Inherits:
Hash
  • Object
show all
Defined in:
lib/base_convert/digits.rb

Instance Method Summary collapse

Constructor Details

#initializeDigits

Returns a new instance of Digits.



3
4
5
# File 'lib/base_convert/digits.rb', line 3

def initialize
  @registry = [:P95, :B64, :U47, :G94, :Q91, :W63]
end

Instance Method Details

#[](key) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/base_convert/digits.rb', line 9

def [](key)
  return (_=get key).is_a?(Symbol)?self[_]:_ if self.has_key? key
  case key
  when Symbol
    chars = Chars.new
    key.to_s.scan(/[+-]?[[:alnum:]]+/).each do |type|
      if self.has_key?(_=type.to_sym)
        chars.add super(_)
        next
      end
      case type
      when /^((u\h+)|(k\d+))+$/ # add single char by code
        type.scan(/[uk]\h+/).each{chars.top _1.to_sym}
      when /^(([ij]\d+)|([vw]\h+))+$/ # set start/stop range
        type.scan(/[ijvw]\h+/).each{chars.set _1}
      when /^[a-z][a-z]+$/ # add by POSIX bracket expression
        chars.add Regexp.new "[[:#{type}:]]"
      when /^[a-z]$/ # add by metacharacter
        chars.add Regexp.new "\\#{type}"
      when /^[A-Z]+$/i # add by property
        type.scan(/[A-Z][a-z]*/).each{chars.add(/\p{#{_1}}/)}
      when /^([+-])(\w+)$/ # top or remove chars of key given
        (_=self[$2.to_sym]) and ($1=='+')? chars.top(_): chars.remove(_)
      when /^(\p{L}+)(\d+)$/ # a registered set
        l,m = $1,$2.to_i-1
        n = self.keys.select{_1=~/^#{l}\d+$/}
          .map{_1.to_s.sub(l,'').to_i}.max
        raise "no #{l}<n> digits defined" if n.nil?
        raise "out of range of #{l}#{n}" unless m<n
        chars.add self[:"#{l}#{n}"][0..m]
      else
        raise "unrecognized digits key: #{type}"
      end
    end
    return chars.to_s.freeze
  when String
    _=@registry.lazy.map{self[_1]}.detect{_1.start_with? key} and return _
    raise 'need at least 2 digits' unless key.length > 1
    if key.length > key.chars.uniq.length
      raise 'digits must not have duplicates'
    end
    return key
  when Integer
    raise 'need digits to cover base' if key > 95
    return self[:P95] # Defined in configuration.rb
  end
  raise 'digits must be String|Symbol|Integer'
end

#forget!(keys = @registry) ⇒ Object



79
80
81
82
83
84
85
86
87
88
# File 'lib/base_convert/digits.rb', line 79

def forget!(keys=@registry)
  [*keys].each do |k|
    # follow Symbol links 'till nil|String
    while s = get(k) and not s.is_a? String
      raise 'expected Symbol' unless s.is_a? Symbol
      k = s
    end
    self.delete(k) if s
  end
end

#getObject

Set super’s [] definition as get



8
# File 'lib/base_convert/digits.rb', line 8

alias :get :[]

#label(d) ⇒ Object



64
65
66
# File 'lib/base_convert/digits.rb', line 64

def label(d)
  registry(d) or (d[0..1]+d[-2..-1]).to_sym
end

#memoize!(keys = @registry) ⇒ Object



68
69
70
71
72
73
74
75
76
77
# File 'lib/base_convert/digits.rb', line 68

def memoize!(keys=@registry)
  [*keys].each do |k|
    # follow Symbol links 'till nil|String
    while s=get(k) and not s.is_a? String
      raise 'expected Symbol' unless s.is_a? Symbol
      k = s
    end
    self[k]=self[k] unless s # memoize if needed
  end
end

#registry(d = nil) ⇒ Object



58
59
60
61
62
# File 'lib/base_convert/digits.rb', line 58

def registry(d=nil)
  # BaseConvert::Number memoizes and uses specifically :P95, :B64, and :U47;
  # giving these precedence above the rest.
  d ? @registry.detect{|_|self[_].start_with? d}: @registry
end