chrad 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b2496ecbaa44e120f9be12f8850bafcbc91cb6be85fde1d89afe392260829fd7
4
+ data.tar.gz: b86d3009434f1ac3007fbda668d3c671d56e98227896ee66a3c4576b896b9367
5
+ SHA512:
6
+ metadata.gz: 74a95665031363af6adb52cd4daf79f1564864164479055b60906e01d60474eac2ca9c50803447cb34b71ea62b4c2bb3409363b8ae5c22ff0d3a422c8533c62a
7
+ data.tar.gz: d7c89246f637683d07b8166d5f681688323514105d8adc7b0db69864e3288a05b8489492254cd33ab5434c25a5c45f44232432f1160f5024a0688491367d0407
checksums.yaml.gz.sig ADDED
Binary file
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in chrad.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "minitest", "~> 5.0"
8
+
9
+ gem "byebug", "~> 11.1", :groups => [:development, :test]
data/Gemfile.lock ADDED
@@ -0,0 +1,23 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ chrad (1.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ byebug (11.1.3)
10
+ minitest (5.16.2)
11
+ rake (12.3.3)
12
+
13
+ PLATFORMS
14
+ x86_64-linux
15
+
16
+ DEPENDENCIES
17
+ byebug (~> 11.1)
18
+ chrad!
19
+ minitest (~> 5.0)
20
+ rake (~> 12.0)
21
+
22
+ BUNDLED WITH
23
+ 2.3.9
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Brent Sanders
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # ChRad
2
+
3
+ Change Radix. A command line utility to convert integer bases.
4
+
5
+ Arbitrarily large numbers are supported thanks to ruby's built-in
6
+ support for bignums. Conversion to or from any positive integer fixed
7
+ base system is supported.
8
+
9
+ Mixed-radix systems are not supported. For converting numbers in the factoradic
10
+ (factorial base) system, use my [factoradic gem][fact_gem] or [faster c utility][c_util].
11
+
12
+ [fact_gem]: https://github.com/pdkl95/factoradic
13
+
14
+ [c_util]: https://github.com/pdkl95/factoradic_c_utils
15
+
16
+
17
+ ## Installation
18
+
19
+ Run:
20
+
21
+ gem install chrad
22
+
23
+
24
+ ## Usage
25
+
26
+ ### The command line utility
27
+
28
+ #### Options
29
+
30
+ ```
31
+ Usage: chrad [options] -i <input_base> -o <output_base> <number> [...]
32
+
33
+ REQUIRED OPTIONS
34
+
35
+ -i, --input=BASE Interpret input strings integers in base <BASE>
36
+ -o, --output=BASE Print converted numbers as integers in base <BASE>
37
+
38
+ INPUT/OUTPUT FORMAT
39
+
40
+ --input-list Input values as delimiter separated lists
41
+ --output-list Output values as delimiter separated lists
42
+ -l, --list Both input and output values as delimiter separated lists
43
+ (Shorthand for using both --input-list and --output-list)
44
+ --input-sep=CHAR Use <CHAR> as the delimiter between places
45
+ in input vales when using --input-list mode
46
+ --output-sep=CHAR Use <CHAR> as the delimiter between places
47
+ in output vales when using --output-list mode
48
+ -s, --separator=CHAR Use <CHAR> as the delimiter between places in both
49
+ input and output list modes. (shorthand for using
50
+ both --input-separator=CHAR and --output-separator=CHAR)
51
+
52
+ DIGIT ALPHABET
53
+
54
+ --input-digits=STR Use the given <STR> as the set of chars to use
55
+ when interpreting input integers.
56
+ (Ignored when using--input-list mode.)
57
+ --output-digits=STR Use the given <STR> as the set of chars to use
58
+ when printing number in the output base.
59
+ (Ignored when using--input-list mode.)
60
+ -d, --digits=STR Use the given <STR> as the set of chars to use
61
+ for both input and output. (shorthand for using
62
+ both --input-digits=STR and --output-digits=STR)
63
+
64
+ --list-named-digits List the built-in named digit sets. These names
65
+ can be passed to any of --digits, --input-digits,
66
+ or --output-digits using the \"name:\" prefix.
67
+ (example: \"--digits=base64\")
68
+ -h, --help Show this help message
69
+ --version Show version
70
+ ```
71
+
72
+
73
+ #### Examples
74
+
75
+ ```
76
+ $ chrad -i 10 -o 16 255
77
+ ff
78
+
79
+ $ chrad -i 16 -o 2 c9
80
+ 11001001
81
+
82
+ $ chrad -i 10 -o 64 --output-digits=name:base64 129633344153503
83
+ deadbeef
84
+
85
+ $ chrad -i 10 -o 64 --output-list 129633344153503
86
+ 29,30,26,29,27,30,30,31
87
+
88
+ $ chrad -i 64 -o 64 --input-list --output-digits=name:base64 29,30,26,29,27,30,30,31
89
+ deadbeef
90
+
91
+ $ chrad -i 10 -o 4 --output-digits='♠♡♢♣' 4321
92
+ ♡♠♠♣♢♠♡
93
+
94
+ $ print3nums() { echo 255 ; echo 65535 ; echo 16777215 ; }
95
+ $ print3nums | chrad -i 10 -o 16 --stdin
96
+ ff
97
+ ffff
98
+ ffffff
99
+ ```
100
+
101
+
102
+ ### Input/Output
103
+
104
+ To represent a number in a given base, a set of digits must be available
105
+ that is at least as large as that base. To support this, chrad allows
106
+ you to provide a string of characters to use for input, output, or
107
+ both (with `--input-digits`, `--output-digits`, and `--digits`
108
+ respectively).
109
+
110
+ ```
111
+ $ chrad -i 16 -o 3 --output-digits .-/ 5717063
112
+ /.-../---/...-/./
113
+ ```
114
+
115
+
116
+ #### Built-in Digit Sets
117
+
118
+ Several commonly used sets of digits are built-in. To use a built-in
119
+ set, use the name of the wet with the `--digits` options and a `name:`
120
+ prefix.
121
+
122
+ ```
123
+ $ chrad -i 16 -o 64 --output-digits=name:base64 dea
124
+ ```
125
+
126
+ The built-in digit sets are:
127
+ ```
128
+ $ chrad --list-named-digits
129
+ name:base62 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
130
+ name:base64 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
131
+ name:base64url ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
132
+ name:base32rfc ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
133
+ name:base32 0123456789abcdefghijklmnopqrstuv
134
+ name:base16 0123456789abcdef
135
+ ```
136
+
137
+ The sets `base16` and `base32` are the common hexadecimal-style
138
+ extension of the base 10 digits. The sets `base64`, `base64url`, and
139
+ `base32rfc` are from [RFC 3548][rfc3548].
140
+
141
+ [rfc3548]: https://datatracker.ietf.org/doc/html/rfc3548
142
+
143
+
144
+ #### List Mode
145
+
146
+ When converting numbers in very large bases, finding appropriate
147
+ characters to use becomes difficult. To avoid this problem, use list
148
+ mode. List mode can also make integration easier because it is a
149
+ base-independent representation.
150
+
151
+ List mode can be enabled for input, output, or both with
152
+ `--input-list`, `--output-list`, and `-l/--list` respectively. When
153
+ list mode is enabled, numbers are represented as a comma (`","`)
154
+ separated list of base 10 integers.
155
+
156
+ ```
157
+ $ chrad -i 10 -o 64 --output-list 16772988
158
+ 63,62,61,60
159
+
160
+ $ chrad -i 64 -o 16 --input-list 3,30,43,27,59,47
161
+ deadbeef
162
+
163
+ $ chrad -i 8 -o 16 --list 5,4,3,2,1
164
+ 5,8,13,1
165
+ ```
166
+
167
+ The comma separator can be changed to any character with the
168
+ `--input-sep`, `--output-sep`, and `-s/--separator` options.
169
+
170
+ ```
171
+ $ chrad -i 10 -o 64 --output-list --output-sep=: 16772988
172
+ 63:62:61:60
173
+ ```
174
+
175
+
176
+ ## Development
177
+
178
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
179
+
180
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
181
+
182
+ ## Contributing
183
+
184
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pdkl95/chrad.
185
+
186
+ ## License
187
+
188
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.warning = false
10
+ t.test_globs = ["test/**/*_test.rb"]
11
+ end
12
+
13
+ task default: :test
data/certs/pdkl95.pem ADDED
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEMDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDDBZwZGts
3
+ OTUvREM9Z21haWwvREM9Y29tMB4XDTIyMDIwMTIxNDQxMFoXDTIzMDIwMTIxNDQx
4
+ MFowITEfMB0GA1UEAwwWcGRrbDk1L0RDPWdtYWlsL0RDPWNvbTCCAaIwDQYJKoZI
5
+ hvcNAQEBBQADggGPADCCAYoCggGBAJrJqYa1q3ckmQ6L0v5r2KpJLFrks7L9cmpO
6
+ qdo3QdUZqnBbIIuhkUOy+rzUM//lCvZeT2Rym8zysJWslATnjhqoKdC6HhAnM7u8
7
+ puI1Xgr0vy84YCc4Ec0iRyrUQkwRB0flQ1XzmH4CJzMD9HafjF0JbCakoawxYsWu
8
+ A8DJ4mZn8sdz0BjGF5nHaLtt/cTx4FQpHLcU6AJSep0BP+fn87HGsrvhLEcITx5v
9
+ 8KYnWAdCEiSVCprmANn0rEeD/vCONotRdUBGSmx6aYV/ijujS+ND7a0hk8d3lhkk
10
+ yvW9L4GM6i3lDsM/wlNBG/HwJuuI06Nve/FC53XYUbh6oyszHiwf8F3jpd9LVHiz
11
+ hO05+X59sJfbC26k8HdsI8/hodDJfgJ4VM5sOqqg3yKV8h6kySiGFSr1XeWddblg
12
+ Zz5jRp85cQsLQWUKWBfxGG3Jnqe8h+aflTaUqnU1EWkEyS0BsotZAFD5t5yX55WD
13
+ dlaJPfF7IyJABxsY+L9LvmWUPFx4RwIDAQABo3MwcTAJBgNVHRMEAjAAMAsGA1Ud
14
+ DwQEAwIEsDAdBgNVHQ4EFgQUsdOGedmK14HgEtn36tJY4fFiPyUwGwYDVR0RBBQw
15
+ EoEQcGRrbDk1QGdtYWlsLmNvbTAbBgNVHRIEFDASgRBwZGtsOTVAZ21haWwuY29t
16
+ MA0GCSqGSIb3DQEBCwUAA4IBgQA481LIo+nYP69SRZgo6Okpii2kO3URi+aR5TLC
17
+ 8BZI/z5/NuYZivMuaMenL90NmeF3LYjmKrOhQD0JmW48YmWQB19b2kIbExBqmu3V
18
+ JomVhCTLZ+oU3NhzQ5fL70DUhOz7CUCKpLV5lsUyUEGjebDFN21j4GjyeDFqkphj
19
+ /d2Qe2I5NLzga3tB1AOBqH0EAf3GSWDp1KkWDSUpUCbhjI+CAu4tpUj74HuCBG4g
20
+ QSTyCS7bp79NUcLmDGJ/43ZgPpJwo6wdV5uo3BQMq8AzRDnTXW1EeGlBOTaDCCvp
21
+ N7ImUU63/qmLKyPskr53EKYR6bzvF4V+w5+Lq/JxWIbaB5UxY1kCxGrOubzQLvwE
22
+ tf/k74CEmUNN71A4MXGVuydmgrlok/LBZO8Lqa9Dt+95nBdqKz5vIcO6szPGZIid
23
+ NMwK52EhsO4bDuwRB7r1zYTj42O24s0o0yJQPzqhfQEGssdLDNkEr147K0symobj
24
+ l35DiP6VyFMH/Y0JWgs65E5bGzk=
25
+ -----END CERTIFICATE-----
data/chrad.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ require_relative "lib/chrad/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "chrad"
5
+ spec.version = ChRad::VERSION
6
+ spec.authors = ["Brent Sanders"]
7
+ spec.email = ["git@gmail.com"]
8
+
9
+ spec.summary = %q{Command line util to convert integer base}
10
+ spec.description = %q{A commsnd line utility to convert integers into arbitrary bases.}
11
+
12
+ spec.homepage = "https://github.com/pdkl95/chrad"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = spec.homepage
18
+
19
+ spec.cert_chain = ['certs/pdkl95.pem']
20
+ spec.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+ end
data/exe/chrad ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'chrad/cli'
4
+
5
+ ChRad::CLI.new(ARGV).run!
@@ -0,0 +1,18 @@
1
+ module ChRad
2
+ module Algorithms
3
+ def self.number_to_base(number, base)
4
+ if number == 0
5
+ return [0]
6
+ end
7
+
8
+ digits = []
9
+ while number > 0
10
+ div, mod = number.divmod(base)
11
+ digits.push(mod)
12
+ number = div
13
+ end
14
+
15
+ digits
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,95 @@
1
+ module ChRad
2
+ class Alphabet
3
+ B62 = (
4
+ ('A'..'Z').to_a +
5
+ ('a'..'z').to_a +
6
+ (0..9).to_a.map(&:to_s)
7
+ )
8
+
9
+ B32rfc = (
10
+ ('A'..'Z').to_a +
11
+ ('2'..'7').to_a
12
+ )
13
+
14
+ B32 = (
15
+ ('0'..'9').to_a +
16
+ ('a'..'v').to_a
17
+ )
18
+
19
+ B16 = (
20
+ ('0'..'9').to_a +
21
+ ('a'..'f').to_a
22
+ )
23
+
24
+ def self.all
25
+ @all ||= Hash.new
26
+ end
27
+
28
+ def self.add(name, digits)
29
+ all[name.to_s] = digits
30
+ end
31
+
32
+ def self.find(name)
33
+ all[name.to_s]
34
+ end
35
+
36
+ def self.[](name)
37
+ find(name)
38
+ end
39
+
40
+ def self.names
41
+ all.keys
42
+ end
43
+
44
+ add :base62, B62
45
+ add :base64, B62 + %w(+ /)
46
+ add :base64url, B62 + %w(- _)
47
+ add :base32rfc, B32rfc
48
+ add :base32, B32
49
+ add :base16, B16
50
+
51
+
52
+ attr_reader :name, :digits
53
+
54
+ def initialize(name, digit_chars)
55
+ @name = name
56
+
57
+ self.digits = digit_chars
58
+ end
59
+
60
+ def digits=(value)
61
+ new_digits = []
62
+ case value
63
+ when String
64
+ self.digits = value.each_char.to_a
65
+
66
+ when Array
67
+ value.each do |ch|
68
+ if new_digits.include?(ch)
69
+ raise InvalidInputError,
70
+ "Cannot add duplicate characters (\"#{ch}\")"
71
+ else
72
+ new_digits.push ch.to_s
73
+ end
74
+ end
75
+
76
+ @digits = new_digits
77
+
78
+ else
79
+ raise Error, "Cannot set digits from a \"${value}\". Expected a list of digits as a String or Array"
80
+ end
81
+ end
82
+
83
+ def [](*args)
84
+ digits[*args]
85
+ end
86
+
87
+ def length
88
+ digits.length
89
+ end
90
+
91
+ def to_s
92
+ digits.join('')
93
+ end
94
+ end
95
+ end
data/lib/chrad/cli.rb ADDED
@@ -0,0 +1,183 @@
1
+ require 'chrad'
2
+ require 'optparse'
3
+
4
+ module ChRad
5
+ class CLI
6
+ attr_reader :argv
7
+
8
+ def initialize(argv = ARGV)
9
+ @argv = argv.map do |x|
10
+ x.to_s
11
+ end
12
+ end
13
+
14
+ def input
15
+ @input ||= ChRad::InputManager.new
16
+ end
17
+
18
+ def output
19
+ @output ||= ChRad::OutputManager.new
20
+ end
21
+
22
+ def optparse
23
+ @optparse ||= OptionParser.new do |opts|
24
+ opts.banner = "Converts integers into a different base (radix)."
25
+ opts.define_head "Usage: #{$0} [options] -i <input_base> -o <output_base> <number> [...]"
26
+ opts.summary_width = 24
27
+ opts.summary_indent = ' '
28
+
29
+ opts.separator ''
30
+ opts.separator 'REQUIRED OPTIONS'
31
+ opts.separator ''
32
+
33
+ opts.on('-iBASE', '--input=BASE',
34
+ 'Interpret input strings integers in base <BASE>'
35
+ ) do |base|
36
+ input.base = base
37
+ end
38
+
39
+ opts.on('-oBASE', '--output=BASE',
40
+ 'Print converted numbers as integers in base <BASE>'
41
+ ) do |base|
42
+ output.base = base
43
+ end
44
+
45
+
46
+ opts.separator ''
47
+ opts.separator 'INPUT/OUTPUT FORMAT'
48
+ opts.separator ''
49
+
50
+ opts.on('--input-list',
51
+ 'Input values as delimiter separated lists'
52
+ ) do
53
+ input.mode = :list
54
+ end
55
+
56
+ opts.on('--output-list',
57
+ 'Output values as delimiter separated lists'
58
+ ) do
59
+ output.mode = :list
60
+ end
61
+
62
+ opts.on('-l', '--list',
63
+ 'Both input and output values as delimiter separated lists',
64
+ '(Shorthand for using both --input-list and --output-list)'
65
+ ) do
66
+ input.mode = :list
67
+ output.mode = :list
68
+ end
69
+
70
+ opts.on('--input-sep=CHAR',
71
+ 'Use <CHAR> as the delimiter between places',
72
+ 'in input vales when using --input-list mode'
73
+ ) do |sep|
74
+ input.separator = sep
75
+ end
76
+
77
+ opts.on('--output-sep=CHAR',
78
+ 'Use <CHAR> as the delimiter between places',
79
+ 'in output vales when using --output-list mode'
80
+ ) do |sep|
81
+ output.separator = sep
82
+ end
83
+
84
+ opts.on('-s', '--separator=CHAR',
85
+ 'Use <CHAR> as the delimiter between places in both',
86
+ 'input and output list modes. (shothand for using',
87
+ 'both --input-separator=CHAR and --output-separator=CHAR)'
88
+ ) do |sep|
89
+ input.separator = sep
90
+ output.separator = sep
91
+ end
92
+
93
+ opts.separator ''
94
+ opts.separator 'DIGIT ALPHABET'
95
+ opts.separator ''
96
+
97
+ opts.on('--input-digits=STR',
98
+ 'Use the given <STR> as the set of chars to use',
99
+ 'when interpreting input integers.',
100
+ '(Ignored when using--input-list mode.)'
101
+ ) do |str|
102
+ input.alphabet = str
103
+ end
104
+
105
+ opts.on('--output-digits=STR',
106
+ 'Use the given <STR> as the set of chars to use',
107
+ 'when printing number in the output base.',
108
+ '(Ignored when using--input-list mode.)'
109
+ ) do |str|
110
+ output.alphabet = str
111
+ end
112
+
113
+ opts.on('-d', '--digits=STR',
114
+ 'Use the given <STR> as the set of chars to use',
115
+ 'for both input and output. (shorthand for using',
116
+ 'both --input-digits=STR and --output-digits=STR)'
117
+ ) do |str|
118
+ input.alphabet = str
119
+ output.alphabet = str
120
+ end
121
+
122
+
123
+ opts.separator ''
124
+
125
+ opts.on('--stdin',
126
+ 'Read one number per line from STDIN instead',
127
+ 'of ARGV. Equivalent to using the single',
128
+ 'character "-" as the first arg.'
129
+ ) do
130
+ input.force_stdin = true
131
+ end
132
+
133
+ opts.on('--list-named-digits',
134
+ 'List the built-in named digit sets. These names',
135
+ 'can be passed to any of --digits, --input-digits,',
136
+ 'or --output-digits using the \"name:\" prefix.',
137
+ '(example: \"--digits=base64\")'
138
+ ) do
139
+ Alphabet.all.each_pair do |name, digits|
140
+ puts "name:#{name}\t#{digits.join('')}"
141
+ end
142
+ exit
143
+ end
144
+
145
+ opts.on('-h', '--help', 'Show this help message') do
146
+ puts opts
147
+ exit
148
+ end
149
+
150
+ opts.on('--version', 'Show version') do
151
+ puts ChRad::VERSION
152
+ exit
153
+ end
154
+ end
155
+ end
156
+
157
+ def run!
158
+ optparse.parse!(argv)
159
+
160
+ if argv.length > 0
161
+ unless argv.first == '-'
162
+ unless input.force_stdin
163
+ input.stream = argv
164
+ end
165
+ end
166
+ else
167
+ unless input.force_stdin
168
+ puts optparse
169
+ exit 1
170
+ end
171
+ end
172
+
173
+ input.setup_base_digits!
174
+ output.setup_base_digits!
175
+
176
+ input.stream.each do |arg|
177
+ arg = arg.chomp
178
+ number = input.parse(arg)
179
+ output.stream_puts(number)
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,136 @@
1
+ require_relative 'algorithms'
2
+
3
+ module ChRad
4
+ class IOManager
5
+ attr_accessor :stream, :base
6
+ attr_writer :mode, :separator
7
+ attr_reader :digits
8
+
9
+ def mode
10
+ @mode ||= DEFAULT_MODE
11
+ end
12
+
13
+ def base=(value)
14
+ case value
15
+ when Integer
16
+ @base = value
17
+ when /\A[0-9]+\Z/
18
+ @base = value.to_i
19
+ else
20
+ raise Error, "Trying to set #{name} base to #{value.inspect} (expected an Integer or a string matching /[0-9]+/"
21
+ end
22
+ end
23
+
24
+ def separator
25
+ @separator ||= DEFAULT_SEPARATOR
26
+ end
27
+
28
+ def alphabet
29
+ @alphabet ||= DEFAULT_ALPHABET
30
+ end
31
+
32
+ def alphabet=(str)
33
+ @alphabet = automagic_find_alphabet(str)
34
+ end
35
+
36
+ def automagic_find_alphabet(str)
37
+ case str
38
+ when /\Aname:(\w+)\Z/
39
+ Alphabet.find($1) or raise Error, "No digit alphabet named \"#{$1}\""
40
+ else
41
+ Alphabet.new("custom_#{name}", str)
42
+ end
43
+ end
44
+
45
+ def setup_base_digits!
46
+ case mode
47
+ when :alphabet
48
+ if base > alphabet.length
49
+ raise Error, "Trying to use base #{base}, but the input alphabet only has #{alphabet.length} characters."
50
+ end
51
+
52
+ @digits = alphabet[0, base]
53
+
54
+ when :list
55
+ # not needed in :list mode
56
+
57
+ else
58
+ raise Error, "Invalid mode #{mode.inspect}"
59
+ end
60
+ end
61
+
62
+ def value_to_digit(value)
63
+ raise Error, '@digits == nil' if @digits.nil?
64
+ @digits[value]
65
+ end
66
+ end
67
+
68
+ class InputManager < IOManager
69
+ attr_accessor :force_stdin
70
+
71
+ def initialize
72
+ @base = DEFAULT_INPUT_BASE
73
+ @stream = $stdin
74
+ @force_stdin = false
75
+ end
76
+
77
+ def name
78
+ 'input'
79
+ end
80
+
81
+ def parse(str)
82
+ case mode
83
+ when :alphabet
84
+ str.reverse.each_char.map.with_index do |c, idx|
85
+ value = digits.index(c)
86
+ if value.nil?
87
+ raise Error, "Input digit #{c.inspect} is not a valid input digit (expected: #{digits.join('')})"
88
+ end
89
+ value * (base ** idx)
90
+ end.reduce(&:+)
91
+
92
+ when :list
93
+ digits = str.split(separator).reverse
94
+ digits.map.with_index do |x,idx|
95
+ x.to_i * (base ** idx)
96
+ end.reduce(&:+)
97
+
98
+ else
99
+ raise Error, "Invalid mode #{mode.inspect}"
100
+ end
101
+ end
102
+ end
103
+
104
+ class OutputManager < IOManager
105
+ def initialize
106
+ @base = DEFAULT_OUTPUT_BASE
107
+ @stream = $stdout
108
+ end
109
+
110
+ def name
111
+ 'output'
112
+ end
113
+
114
+ def number_to_string(number)
115
+ list = Algorithms.number_to_base(number, base)
116
+ list.reverse!
117
+
118
+ case mode
119
+ when :alphabet
120
+ list.map do |value|
121
+ value_to_digit(value)
122
+ end.join('')
123
+
124
+ when :list
125
+ list.join(separator)
126
+
127
+ else
128
+ raise Error, "Invalid mode #{mode.inspect}"
129
+ end
130
+ end
131
+
132
+ def stream_puts(number)
133
+ stream.puts number_to_string(number)
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,3 @@
1
+ module ChRad
2
+ VERSION = "1.1.0"
3
+ end
data/lib/chrad.rb ADDED
@@ -0,0 +1,20 @@
1
+ require_relative "chrad/version"
2
+
3
+ module ChRad
4
+ class Error < StandardError; end
5
+ class InvalidInputError < Error; end
6
+
7
+ DEFAULT_BASE = 10
8
+ DEFAULT_INPUT_BASE = DEFAULT_BASE
9
+ DEFAULT_OUTPUT_BASE = DEFAULT_BASE
10
+
11
+ DEFAULT_MODE = :alphabet
12
+ DEFAULT_SEPARATOR = ','
13
+ end
14
+
15
+ require_relative 'chrad/alphabet'
16
+ require_relative 'chrad/io_manager'
17
+
18
+ module ChRad
19
+ DEFAULT_ALPHABET = Alphabet[:base16]
20
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chrad
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brent Sanders
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEMDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDDBZwZGts
14
+ OTUvREM9Z21haWwvREM9Y29tMB4XDTIyMDIwMTIxNDQxMFoXDTIzMDIwMTIxNDQx
15
+ MFowITEfMB0GA1UEAwwWcGRrbDk1L0RDPWdtYWlsL0RDPWNvbTCCAaIwDQYJKoZI
16
+ hvcNAQEBBQADggGPADCCAYoCggGBAJrJqYa1q3ckmQ6L0v5r2KpJLFrks7L9cmpO
17
+ qdo3QdUZqnBbIIuhkUOy+rzUM//lCvZeT2Rym8zysJWslATnjhqoKdC6HhAnM7u8
18
+ puI1Xgr0vy84YCc4Ec0iRyrUQkwRB0flQ1XzmH4CJzMD9HafjF0JbCakoawxYsWu
19
+ A8DJ4mZn8sdz0BjGF5nHaLtt/cTx4FQpHLcU6AJSep0BP+fn87HGsrvhLEcITx5v
20
+ 8KYnWAdCEiSVCprmANn0rEeD/vCONotRdUBGSmx6aYV/ijujS+ND7a0hk8d3lhkk
21
+ yvW9L4GM6i3lDsM/wlNBG/HwJuuI06Nve/FC53XYUbh6oyszHiwf8F3jpd9LVHiz
22
+ hO05+X59sJfbC26k8HdsI8/hodDJfgJ4VM5sOqqg3yKV8h6kySiGFSr1XeWddblg
23
+ Zz5jRp85cQsLQWUKWBfxGG3Jnqe8h+aflTaUqnU1EWkEyS0BsotZAFD5t5yX55WD
24
+ dlaJPfF7IyJABxsY+L9LvmWUPFx4RwIDAQABo3MwcTAJBgNVHRMEAjAAMAsGA1Ud
25
+ DwQEAwIEsDAdBgNVHQ4EFgQUsdOGedmK14HgEtn36tJY4fFiPyUwGwYDVR0RBBQw
26
+ EoEQcGRrbDk1QGdtYWlsLmNvbTAbBgNVHRIEFDASgRBwZGtsOTVAZ21haWwuY29t
27
+ MA0GCSqGSIb3DQEBCwUAA4IBgQA481LIo+nYP69SRZgo6Okpii2kO3URi+aR5TLC
28
+ 8BZI/z5/NuYZivMuaMenL90NmeF3LYjmKrOhQD0JmW48YmWQB19b2kIbExBqmu3V
29
+ JomVhCTLZ+oU3NhzQ5fL70DUhOz7CUCKpLV5lsUyUEGjebDFN21j4GjyeDFqkphj
30
+ /d2Qe2I5NLzga3tB1AOBqH0EAf3GSWDp1KkWDSUpUCbhjI+CAu4tpUj74HuCBG4g
31
+ QSTyCS7bp79NUcLmDGJ/43ZgPpJwo6wdV5uo3BQMq8AzRDnTXW1EeGlBOTaDCCvp
32
+ N7ImUU63/qmLKyPskr53EKYR6bzvF4V+w5+Lq/JxWIbaB5UxY1kCxGrOubzQLvwE
33
+ tf/k74CEmUNN71A4MXGVuydmgrlok/LBZO8Lqa9Dt+95nBdqKz5vIcO6szPGZIid
34
+ NMwK52EhsO4bDuwRB7r1zYTj42O24s0o0yJQPzqhfQEGssdLDNkEr147K0symobj
35
+ l35DiP6VyFMH/Y0JWgs65E5bGzk=
36
+ -----END CERTIFICATE-----
37
+ date: 2022-07-12 00:00:00.000000000 Z
38
+ dependencies: []
39
+ description: A commsnd line utility to convert integers into arbitrary bases.
40
+ email:
41
+ - git@gmail.com
42
+ executables:
43
+ - chrad
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - Gemfile
48
+ - Gemfile.lock
49
+ - LICENSE.txt
50
+ - README.md
51
+ - Rakefile
52
+ - certs/pdkl95.pem
53
+ - chrad.gemspec
54
+ - exe/chrad
55
+ - lib/chrad.rb
56
+ - lib/chrad/algorithms.rb
57
+ - lib/chrad/alphabet.rb
58
+ - lib/chrad/cli.rb
59
+ - lib/chrad/io_manager.rb
60
+ - lib/chrad/version.rb
61
+ homepage: https://github.com/pdkl95/chrad
62
+ licenses:
63
+ - MIT
64
+ metadata:
65
+ homepage_uri: https://github.com/pdkl95/chrad
66
+ source_code_uri: https://github.com/pdkl95/chrad
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 2.3.0
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubygems_version: 3.1.4
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: Command line util to convert integer base
86
+ test_files: []
metadata.gz.sig ADDED
Binary file