chrad 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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