base_convert 3.0.191224 → 3.1.191231
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +40 -15
- data/lib/base_convert.rb +5 -27
- data/lib/base_convert/base_convert.rb +23 -0
- data/lib/base_convert/configuration.rb +23 -22
- data/lib/base_convert/from_to.rb +1 -2
- data/lib/base_convert/number.rb +64 -107
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09e96875804850531f1e4e890eeac10d8a53275be55d875f3ea262a03624218d'
|
4
|
+
data.tar.gz: c374bb673c441bb11c314accdcd1b2afef057cf1e23252225cbf08347c83c9ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05ddba6c9079bf3c8a737b8e176e52f560beb6d19ed8aadda1230bd2f09691c112ffbf52cf5b329853f5dd96ab31ade73553938fb83eb7c29783337105bbd31b
|
7
|
+
data.tar.gz: 2b246aeea822d1aa57b281bc6bc93eb118751c86f938dea9c2eb719741efb53c0ca4e5dc7c26f2d38eb81ee535adc9a8d8cc7226c40de931dd087561f5fa741f
|
data/README.md
CHANGED
@@ -69,21 +69,42 @@ You can work with arbitrary digits:
|
|
69
69
|
toi('&&&&', base, digits) #=> 4095
|
70
70
|
tob(4095, base, digits) #=> "&&&&"
|
71
71
|
|
72
|
-
|
72
|
+
Note that one can always explicitly specify the ordered digits to be used.
|
73
|
+
But for convenience, `base_convert` provides some predefined sets of digits:
|
73
74
|
|
74
|
-
* `GRAPH
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
* `
|
79
|
-
|
75
|
+
* `GRAPH :graph :g`, the ASCII graph characters:
|
76
|
+
|
77
|
+
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
|
78
|
+
|
79
|
+
* `QGRAPH :qgraph :q`, the ASCII graph characters except `QUOTES`:
|
80
|
+
|
81
|
+
!#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~
|
82
|
+
|
83
|
+
* `BASE64 :base64 :b64`, the standard base 64 digits from people with no sense of order:
|
84
|
+
|
85
|
+
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
|
86
|
+
|
87
|
+
* `WORD_ :word_ :w_`, the ASCII word characters including `UNDERSCORE`:
|
88
|
+
|
89
|
+
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
|
90
|
+
|
91
|
+
* `WORD :word :w`, the ASCII word characters except `UNDERSCORE`:
|
92
|
+
|
93
|
+
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
94
|
+
|
95
|
+
* `UNAMBIGUOUS :unambigous :u`, the characters in `WORD` without the `AMBIGUOUS` characters(B8G6I1l0OQDS5Z2):
|
96
|
+
|
97
|
+
3479ACEFHJKLMNPRTUVWXYabcdefghijkmnopqrstuvwxyz
|
98
|
+
|
99
|
+
* `G94 :g94` is the library's default defined as `WORD+QGRAPH.delete(WORD_)+QUOTES+UNDERSCORE`
|
100
|
+
|
101
|
+
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+,-./:;<=>?@[\]^{|}~"'`_
|
80
102
|
|
81
103
|
Some examples:
|
82
104
|
|
83
|
-
|
105
|
+
UNAMBIGUOUS #=> "3479ACEFHJKLMNPRTUVWXYabcdefghijkmnopqrstuvwxyz"
|
84
106
|
# etc...
|
85
|
-
tob 255, 16,
|
86
|
-
include Configuration
|
107
|
+
tob 255, 16, WORD #=> "FF"
|
87
108
|
tob 255, 64, BASE64 #=> "D/"
|
88
109
|
|
89
110
|
The second way to convert is via a conversion object of `BaseConvert::FromTo`.
|
@@ -101,11 +122,7 @@ The third way to work with variant base and digits numbers is via the `BaseConve
|
|
101
122
|
hexadecimal.to_i #=> 65535
|
102
123
|
|
103
124
|
# Number will infer your most likely meaning:
|
104
|
-
Number.new('FF'
|
105
|
-
|
106
|
-
# And given a string of at least length 8,
|
107
|
-
# it'll go ahead and guess at your meaning:
|
108
|
-
Number.new('FFFFFFFF').to_i #=> 4294967295
|
125
|
+
Number.new('FF').to_i #=> 255
|
109
126
|
|
110
127
|
# But best practice is to fully specify,
|
111
128
|
# which is easy to do with keys:
|
@@ -135,6 +152,7 @@ one can use a mnemonic key:
|
|
135
152
|
|
136
153
|
| long key | short key | DIGITS | BASE NUMBER |
|
137
154
|
| -------------- | --------- | ------------- | ----------- |
|
155
|
+
| `:g94` | | `G94` | 94 |
|
138
156
|
| `:graph` | `:g` | `GRAPH` | 94 |
|
139
157
|
| `:qgraph` | `:q` | `QGRAPH` | 91 |
|
140
158
|
| `:base64` | `:b64` | `BASE64` | 64 |
|
@@ -149,6 +167,13 @@ one can use a mnemonic key:
|
|
149
167
|
| `:octal` | `:oct, :o` | 8 |
|
150
168
|
| `:binary` | `:bin, :b` | 2 |
|
151
169
|
|
170
|
+
Example:
|
171
|
+
|
172
|
+
# For some pseudo-random string of unambigous characters
|
173
|
+
# of very likely length 16:
|
174
|
+
p = BaseConvert::Number.new(rand(47**16), digits: :u)
|
175
|
+
p.to_s #=> "CxesjJqHcvpnp7bp"
|
176
|
+
|
152
177
|
## LICENSE:
|
153
178
|
|
154
179
|
(The MIT License)
|
data/lib/base_convert.rb
CHANGED
@@ -1,30 +1,8 @@
|
|
1
|
-
# http://rosettacode.org/wiki/Non-decimal_radices/Convert#Ruby
|
2
1
|
module BaseConvert
|
3
|
-
VERSION = '3.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
index = digits.index(c)
|
9
|
-
integer = integer * base + index
|
10
|
-
end
|
11
|
-
integer
|
12
|
-
end
|
13
|
-
|
14
|
-
def tob(integer=@integer, base=@base, digits=@digits)
|
15
|
-
return digits[0] if integer == 0
|
16
|
-
string = ''
|
17
|
-
while integer > 0
|
18
|
-
integer, index = integer.divmod(base)
|
19
|
-
string = string.insert(0, digits[index])
|
20
|
-
end
|
21
|
-
string
|
22
|
-
end
|
23
|
-
|
24
|
-
extend self
|
25
|
-
|
26
|
-
autoload :Configuration, 'base_convert/configuration'
|
27
|
-
autoload :FromTo, 'base_convert/from_to'
|
28
|
-
autoload :Number, 'base_convert/number'
|
2
|
+
VERSION = '3.1.191231'
|
3
|
+
require 'base_convert/base_convert'
|
4
|
+
require 'base_convert/configuration'
|
5
|
+
require 'base_convert/from_to'
|
6
|
+
require 'base_convert/number'
|
29
7
|
end
|
30
8
|
#`ruby`
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# http://rosettacode.org/wiki/Non-decimal_radices/Convert#Ruby
|
2
|
+
module BaseConvert
|
3
|
+
def toi(string=@string, base=@base, digits=@digits)
|
4
|
+
integer = 0
|
5
|
+
string.each_char do |c|
|
6
|
+
index = digits.index(c)
|
7
|
+
integer = integer * base + index
|
8
|
+
end
|
9
|
+
integer
|
10
|
+
end
|
11
|
+
|
12
|
+
def tob(integer=@integer, base=@base, digits=@digits)
|
13
|
+
return digits[0] if integer == 0
|
14
|
+
string = ''
|
15
|
+
while integer > 0
|
16
|
+
integer, index = integer.divmod(base)
|
17
|
+
string = string.insert(0, digits[index])
|
18
|
+
end
|
19
|
+
string
|
20
|
+
end
|
21
|
+
|
22
|
+
extend self
|
23
|
+
end
|
@@ -1,24 +1,26 @@
|
|
1
1
|
module BaseConvert
|
2
|
-
|
3
|
-
|
4
|
-
GRAPH = 0.upto(255).map{|i| i.chr}.select{|c| c=~/[[:graph:]]/}.join.freeze
|
5
|
-
QGRAPH = GRAPH.delete(%('"`)).freeze
|
6
|
-
|
7
|
-
WORD_ = 0.upto(255).map{|i| i.chr}.select{|c| c=~/\w/}.join.freeze
|
8
|
-
WORD = WORD_.delete('_').freeze
|
9
|
-
INDEXa = WORD.index('a')
|
10
|
-
|
2
|
+
QUOTES = %("'`).freeze
|
3
|
+
UNDERSCORE = '_'.freeze
|
11
4
|
AMBIGUOUS = 'B8G6I1l0OQDS5Z2'.freeze
|
5
|
+
|
6
|
+
GRAPH = 0.upto(255).map{|i| i.chr}.select{|c| c=~/[[:graph:]]/}.join.freeze
|
7
|
+
QGRAPH = GRAPH.delete(QUOTES).freeze
|
8
|
+
WORD_ = QGRAPH.chars.select{|c| c=~/\w/}.join.freeze
|
9
|
+
WORD = WORD_.delete(UNDERSCORE).freeze
|
12
10
|
UNAMBIGUOUS = WORD.delete(AMBIGUOUS).freeze
|
11
|
+
G94 = (WORD + QGRAPH.delete(WORD_) + QUOTES + UNDERSCORE).freeze
|
13
12
|
|
14
|
-
BASE64
|
13
|
+
BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.freeze
|
14
|
+
|
15
|
+
INDEXa = G94.index('a')
|
15
16
|
|
16
17
|
BASE = {
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
18
|
+
:g94 => G94.length, # 94
|
19
|
+
:graph => GRAPH.length, # 94
|
20
|
+
:qgraph => QGRAPH.length, # 91
|
21
|
+
:word_ => WORD_.length, # 63
|
22
|
+
:word => WORD.length, # 62
|
23
|
+
:unambiguous => UNAMBIGUOUS.length, # 47
|
22
24
|
:base64 => 64,
|
23
25
|
:b64 => 64,
|
24
26
|
:hexadecimal => 16,
|
@@ -35,13 +37,14 @@ module Configuration
|
|
35
37
|
:b => 2,
|
36
38
|
}
|
37
39
|
|
38
|
-
BASE[:g]
|
39
|
-
BASE[:q]
|
40
|
-
BASE[:w_]
|
41
|
-
BASE[:w]
|
42
|
-
BASE[:u]
|
40
|
+
BASE[:g] = BASE[:graph]
|
41
|
+
BASE[:q] = BASE[:qgraph]
|
42
|
+
BASE[:w_] = BASE[:word_]
|
43
|
+
BASE[:w] = BASE[:word]
|
44
|
+
BASE[:u] = BASE[:unambiguous]
|
43
45
|
|
44
46
|
DIGITS = {
|
47
|
+
:g94 => G94,
|
45
48
|
:graph => GRAPH,
|
46
49
|
:g => GRAPH,
|
47
50
|
:qgraph => QGRAPH,
|
@@ -55,6 +58,4 @@ module Configuration
|
|
55
58
|
:base64 => BASE64,
|
56
59
|
:b64 => BASE64,
|
57
60
|
}
|
58
|
-
|
59
|
-
end
|
60
61
|
end
|
data/lib/base_convert/from_to.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module BaseConvert
|
2
2
|
class FromTo
|
3
|
-
include Configuration
|
4
3
|
include BaseConvert
|
5
4
|
|
6
|
-
def initialize(base: 10, to_base: base, digits:
|
5
|
+
def initialize(base: 10, to_base: base, digits: G94, to_digits: digits)
|
7
6
|
base = BASE[base] if base.is_a? Symbol
|
8
7
|
to_base = BASE[to_base] if to_base.is_a? Symbol
|
9
8
|
digits = DIGITS[digits] if digits.is_a? Symbol
|
data/lib/base_convert/number.rb
CHANGED
@@ -1,129 +1,86 @@
|
|
1
1
|
module BaseConvert
|
2
2
|
class Number
|
3
|
-
include Configuration
|
4
3
|
include BaseConvert
|
5
4
|
|
6
|
-
def
|
7
|
-
if
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
def self.infer(string)
|
6
|
+
return 2, G94 if string.empty?
|
7
|
+
chars = string.chars
|
8
|
+
raise 'Need digits.' unless chars.all?{|_|G94.include?_}
|
9
|
+
max = chars.map{|_|G94.index(_)}.max
|
10
|
+
return 2, G94 if max < 2
|
11
|
+
return 4, G94 if max < 4
|
12
|
+
return 8, G94 if max < 8
|
13
|
+
return 10, G94 if max < 10
|
14
|
+
return 16, G94 if max < 16
|
15
|
+
return 32, G94 if max < 32
|
16
|
+
[UNAMBIGUOUS, BASE64].each do |digits|
|
17
|
+
return digits.length, digits if chars.all?{|_|digits.include?_}
|
13
18
|
end
|
19
|
+
return 64, G94 if max < 64
|
20
|
+
return G94.length, G94 if max < 64
|
14
21
|
end
|
15
22
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if min <= 32
|
23
|
-
raise "Need base for WORD or WORD_." if @string.length < 8
|
24
|
-
return 8 if min <= 8
|
25
|
-
return 16 if min <= 16
|
26
|
-
return 32
|
27
|
-
end
|
28
|
-
when UNAMBIGUOUS
|
29
|
-
if min <= 22
|
30
|
-
raise "Need base for UNAMBIGUOUS." if @string.length < 8
|
31
|
-
return 22
|
32
|
-
end
|
33
|
-
when QGRAPH, GRAPH
|
34
|
-
n = @digits.index 'a'
|
35
|
-
if min <= n
|
36
|
-
raise "Need base for QGRAPH or GRAPH." if @string.length < 8
|
37
|
-
return n
|
38
|
-
end
|
39
|
-
end
|
40
|
-
return max
|
41
|
-
end
|
42
|
-
|
43
|
-
def _digits!
|
44
|
-
if @digits.nil?
|
45
|
-
@digits = @integer.nil? ? _infer_digits_from_string : WORD
|
46
|
-
if @base and @base > @digits.length
|
47
|
-
if @base == 64
|
48
|
-
@digits = BASE64
|
49
|
-
elsif @base <= QGRAPH.length
|
50
|
-
@digits = QGRAPH
|
51
|
-
elsif @base <= GRAPH.length
|
52
|
-
@digits = GRAPH
|
53
|
-
else
|
54
|
-
raise "Need digits that can cover base #{@base}."
|
55
|
-
end
|
56
|
-
end
|
23
|
+
attr_reader :base, :digits
|
24
|
+
def initialize(counter=0, base: nil, digits: nil, validate: true)
|
25
|
+
# validate
|
26
|
+
case validate
|
27
|
+
when true, false
|
28
|
+
@validate = validate
|
57
29
|
else
|
58
|
-
|
59
|
-
digits = DIGITS[@digits]
|
60
|
-
raise "Unrecognized digits #{@digits}." if digits.nil?
|
61
|
-
@digits = digits
|
62
|
-
else
|
63
|
-
raise "digits must be a String of at least length 2." unless @digits.is_a?(String) and @digits.length > 1
|
64
|
-
end
|
30
|
+
raise "validate must be either true of false."
|
65
31
|
end
|
66
|
-
end
|
67
32
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
33
|
+
# counter
|
34
|
+
case counter
|
35
|
+
when String
|
36
|
+
@string = counter
|
37
|
+
base, digits = Number.infer(counter) if base.nil? and digits.nil?
|
38
|
+
when Integer
|
39
|
+
@integer = counter
|
40
|
+
base, digits = 10, G94 if base.nil? and digits.nil?
|
76
41
|
else
|
77
|
-
|
78
|
-
base = BASE[@base]
|
79
|
-
raise "Unrecognized base #{@base}." if base.nil?
|
80
|
-
@base = base
|
81
|
-
else
|
82
|
-
raise "base must be an Integer greater than 1." unless @base.is_a?(Integer) and @base > 1
|
83
|
-
end
|
84
|
-
_digits!
|
42
|
+
raise "Need counter String|Integer."
|
85
43
|
end
|
86
|
-
end
|
87
44
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
raise "digits must cover string." unless @string.chars.all?{|_|@digits.include?_}
|
93
|
-
raise "digits in string must be under base." unless @base > @digits.index(@string.chars.max)
|
45
|
+
# digits
|
46
|
+
if digits.is_a? Symbol
|
47
|
+
digits = DIGITS[digits]
|
48
|
+
raise "Unrecognized digits." if digits.nil?
|
94
49
|
end
|
95
|
-
|
96
|
-
|
50
|
+
digits = DIGITS[base] if digits.nil?
|
51
|
+
digits = G94 if digits.nil?
|
52
|
+
raise "digits must be a String of at least length 2." unless digits.is_a?(String) and digits.length > 1
|
53
|
+
@digits = digits
|
54
|
+
|
55
|
+
# base
|
56
|
+
if base.is_a? Symbol
|
57
|
+
base = BASE[base]
|
58
|
+
raise "Unrecognized base." if base.nil?
|
97
59
|
end
|
98
|
-
|
60
|
+
base = @digits.length if base.nil?
|
61
|
+
raise "base must be an Integer greater than 1." unless base.is_a?(Integer) and base > 1
|
62
|
+
@base = base
|
99
63
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
64
|
+
# validate
|
65
|
+
if @validate
|
66
|
+
raise "digits must cover base." if @base > @digits.length
|
67
|
+
raise "digits must not have duplicates." if @digits.length > @digits.chars.uniq.length
|
68
|
+
unless @string.nil? or @string.empty?
|
69
|
+
@string.upcase! if @base <= INDEXa and @digits.equal? G94
|
70
|
+
raise "digits must cover string." unless @string.chars.all?{|_|@digits.include?_}
|
71
|
+
raise "digits in string must be under base." unless @base > @string.chars.map{|_|@digits.index(_)}.max
|
72
|
+
end
|
73
|
+
unless @integer.nil?
|
74
|
+
raise "integer can't be negative." if @integer < 0
|
75
|
+
end
|
76
|
+
end
|
106
77
|
|
107
|
-
|
108
|
-
|
109
|
-
_validate if @validate
|
110
|
-
@string = tob
|
78
|
+
@integer = toi if @integer.nil?
|
79
|
+
@string = tob if @string.nil?
|
111
80
|
end
|
112
81
|
|
113
|
-
|
114
|
-
|
115
|
-
@base, @digits, @validate = base, digits, validate
|
116
|
-
@string, @integer = nil, nil
|
117
|
-
case counter
|
118
|
-
when String
|
119
|
-
@string = counter
|
120
|
-
_integer!
|
121
|
-
when Integer
|
122
|
-
@integer = counter
|
123
|
-
_string!
|
124
|
-
else
|
125
|
-
raise "Need counter String|Integer."
|
126
|
-
end
|
82
|
+
def validate?
|
83
|
+
@validate
|
127
84
|
end
|
128
85
|
|
129
86
|
def to_s
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: base_convert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.191231
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- carlosjhr64
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-12-
|
11
|
+
date: 2019-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
BaseConvert - Number base conversion.
|
@@ -24,6 +24,7 @@ extra_rdoc_files: []
|
|
24
24
|
files:
|
25
25
|
- README.md
|
26
26
|
- lib/base_convert.rb
|
27
|
+
- lib/base_convert/base_convert.rb
|
27
28
|
- lib/base_convert/configuration.rb
|
28
29
|
- lib/base_convert/from_to.rb
|
29
30
|
- lib/base_convert/number.rb
|
@@ -46,8 +47,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
47
|
- !ruby/object:Gem::Version
|
47
48
|
version: '0'
|
48
49
|
requirements:
|
49
|
-
- 'ruby: ruby 2.
|
50
|
-
rubygems_version: 3.
|
50
|
+
- 'ruby: ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]'
|
51
|
+
rubygems_version: 3.1.2
|
51
52
|
signing_key:
|
52
53
|
specification_version: 4
|
53
54
|
summary: BaseConvert - Number base conversion.
|