qrest 1.0.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.
@@ -0,0 +1,210 @@
1
+ #
2
+ # qrest/segment.rb -- Segments
3
+ #
4
+
5
+ require "qrest/base"
6
+
7
+
8
+ module QRest
9
+
10
+ class Segment
11
+
12
+ def initialize data
13
+ @data = data
14
+ end
15
+
16
+ def write buffer, version
17
+ buffer.put 1<<self.class::ID, 4
18
+ buffer.put @data.bytesize, (get_length_in_bits version)
19
+ end
20
+
21
+ def size version
22
+ 4 + (get_length_in_bits version) + (
23
+ chunk_size, bit_length, extra = cbe
24
+ num, rest = @data.bytesize.divmod chunk_size
25
+ r = num * bit_length
26
+ r += extra if rest.nonzero?
27
+ r
28
+ )
29
+ end
30
+
31
+ private
32
+
33
+ def get_length_in_bits version
34
+ macro_version =
35
+ case version
36
+ when 1.. 9 then 0
37
+ when ..26 then 1
38
+ when ..40 then 2
39
+ else raise Error, "Unknown version: #{version}"
40
+ end
41
+ self.class::BITS_FOR_MODE[macro_version]
42
+ end
43
+
44
+
45
+ @sub = []
46
+
47
+ class <<self
48
+
49
+ def [] *args, **kwargs
50
+ new *args, **kwargs
51
+ end
52
+
53
+ def inherited cls
54
+ @sub.push cls
55
+ end
56
+
57
+ def create data, mode = nil
58
+ case data
59
+ when String then
60
+ if mode then
61
+ type = @sub.find { |t| mode.to_s == t::NAME }
62
+ type or raise ArgumentError, "Not a valid segment type: #{mode}"
63
+ type.new data
64
+ else
65
+ @sub.each do |t|
66
+ break t.new data
67
+ rescue ArgumentError, NotImplementedError
68
+ end
69
+ end
70
+ when Array then
71
+ Multi.new data
72
+ when Segment
73
+ data
74
+ else
75
+ raise ArgumentError, "Data must be a String, an Array, or a Segment"
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+
84
+ class Multi
85
+
86
+ def initialize data
87
+ @segs = data.map! { |s|
88
+ args =
89
+ case s
90
+ when String then s
91
+ when Hash then [ s[ :data], s[ :mode]]
92
+ end
93
+ Segment.create *args
94
+ }
95
+ end
96
+
97
+ def write buffer, version
98
+ @segs.each { |s| s.write buffer, version }
99
+ end
100
+
101
+ def size version
102
+ @segs.sum { |s| s.size version }
103
+ end
104
+
105
+ end
106
+
107
+
108
+ class Numeric < Segment
109
+
110
+ NAME = "number"
111
+ ID = 0
112
+ BITS_FOR_MODE = [10, 12, 14]
113
+
114
+ def initialize data
115
+ data =~ /[^0-9]/ and raise ArgumentError, "Not numeric: #{data}"
116
+ super
117
+ end
118
+
119
+ NUMBER_LENGTH = { 3 => 10, 2 => 7, 1 => 4 }
120
+
121
+ def write buffer, version
122
+ super
123
+ @data.scan /\d{1,3}/ do |chars|
124
+ buffer.put chars.to_i, NUMBER_LENGTH[ chars.length]
125
+ end
126
+ end
127
+
128
+ def cbe ; [3, NUMBER_LENGTH[3], NUMBER_LENGTH[ @data.size % 3]||0] ; end
129
+
130
+ end
131
+
132
+ class Alphanumeric < Segment
133
+
134
+ NAME = "alphanumeric"
135
+ ID = 1
136
+ BITS_FOR_MODE = [ 9, 11, 13]
137
+
138
+ ALPHANUMERIC, = [
139
+ *("0".."9"), *("A".."Z"), " ", "$", "%", "*", "+", "-", ".", "/", ":",
140
+ ].inject [{},0] do |(r,i),e| r[ e] = i ; [r,i+1] end
141
+
142
+ def initialize data
143
+ data.each_char { |c|
144
+ ALPHANUMERIC[ c] or raise ArgumentError, "Not alphanumeric uppercase: #{data}"
145
+ }
146
+ super
147
+ end
148
+
149
+ def write buffer, version
150
+ super
151
+ @data.scan /(.)(.)?/ do |c,d|
152
+ val = ALPHANUMERIC[ c]
153
+ len = 6
154
+ if d then
155
+ val = (val * ALPHANUMERIC.length) + ALPHANUMERIC[ d]
156
+ len += 5
157
+ end
158
+ buffer.put val, len
159
+ end
160
+ end
161
+
162
+ def cbe ; [2, 11, 6] ; end
163
+
164
+ end
165
+
166
+ class Kanji < Segment
167
+
168
+ NAME = "kanji"
169
+ ID = nil # ???
170
+ BITS_FOR_MODE = [ 8, 10, 12]
171
+
172
+ def initialize data
173
+ super
174
+ not_implemented
175
+ end
176
+
177
+ def write buffer, version
178
+ super
179
+ not_implemented
180
+ end
181
+
182
+ def cbe ; not_implemented ; end
183
+
184
+ private
185
+
186
+ def not_implemented
187
+ raise NotImplementedError, "Not implemented yet. Please contribute."
188
+ end
189
+
190
+ end
191
+
192
+ class Bytes < Segment
193
+
194
+ NAME = "8bit"
195
+ ID = 2
196
+ BITS_FOR_MODE = [ 8, 16, 16]
197
+
198
+ def write buffer, version
199
+ super
200
+ @data.each_byte do |b|
201
+ buffer.put b, 8
202
+ end
203
+ end
204
+
205
+ def cbe ; [1, 8, 0] ; end
206
+
207
+ end
208
+
209
+ end
210
+
@@ -0,0 +1,12 @@
1
+ #
2
+ # qrest/version.rb -- Version number
3
+ #
4
+
5
+
6
+ module QRest
7
+
8
+ NAME = "qrest"
9
+ VERSION = "1.0.0"
10
+
11
+ end
12
+
data/lib/qrest.rb ADDED
@@ -0,0 +1,67 @@
1
+ #
2
+ # qrest.rb -- QR code library
3
+ #
4
+
5
+ require "qrest/base"
6
+ require "qrest/version"
7
+ require "qrest/segment"
8
+ require "qrest/rsblocks"
9
+ require "qrest/modules"
10
+
11
+
12
+ module QRest
13
+
14
+ class Code
15
+
16
+ class <<self
17
+ alias [] new
18
+ end
19
+
20
+ attr_reader :modules
21
+
22
+ def initialize input, *more, level: nil, max_version: nil, mode: nil, version: nil
23
+ input = [ input, *more] if not more.empty? or Hash === input
24
+ input = Segment.create input, mode
25
+ level ||= :h
26
+ error_correct_level = level.downcase.to_sym
27
+ Modules::ERRORCORRECTLEVEL[error_correct_level] or
28
+ raise ArgumentError, "Unknown error correction level: #{level}"
29
+ if version then
30
+ version <= Modules::MAX_VERSION or
31
+ raise ArgumentError, "Requested version exceeds maximum of #{Modules::MAX_VERSION}"
32
+ else
33
+ if max_version then
34
+ max_version <= Modules::MAX_VERSION or
35
+ raise ArgumentError, "Maximum posible version is #{Modules::MAX_VERSION}"
36
+ else
37
+ max_version = Modules::MAX_VERSION
38
+ end
39
+ mb = Modules::MAXBITS[error_correct_level]
40
+ version = 0
41
+ begin
42
+ version += 1
43
+ version <= max_version or
44
+ raise Error, "Data length exceeds maximum capacity of version #{max_version}"
45
+ end until (input.size version) <= mb[version - 1]
46
+ end
47
+
48
+ data = (RSBlocks.get version, error_correct_level).create_data input
49
+ @modules = Modules.create_best data, version, error_correct_level
50
+ end
51
+
52
+ def to_s dark: nil, light: nil, quiet_size: nil
53
+ @modules.to_s dark: dark, light: light, quiet_size: quiet_size
54
+ end
55
+
56
+ def method_missing sym, *args, **kwargs, &block
57
+ if @modules.respond_to? sym then
58
+ @modules.send sym, *args, **kwargs, &block
59
+ else
60
+ super
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qrest
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Bertram Scharpf
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-03-16 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: |
13
+ A Ruby library that generates QR Codes
14
+ as XPM, SVG or EPS graphics.
15
+ email: "<software@bertram-scharpf.de>"
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/qrest.rb
21
+ - lib/qrest/base.rb
22
+ - lib/qrest/bch.rb
23
+ - lib/qrest/bitbuffer.rb
24
+ - lib/qrest/bitstream.rb
25
+ - lib/qrest/demerits.rb
26
+ - lib/qrest/foreign/supplement.rb
27
+ - lib/qrest/formats/eps.rb
28
+ - lib/qrest/formats/svg.rb
29
+ - lib/qrest/formats/xpm.rb
30
+ - lib/qrest/modules.rb
31
+ - lib/qrest/polynomial.rb
32
+ - lib/qrest/rsblocks.rb
33
+ - lib/qrest/segment.rb
34
+ - lib/qrest/version.rb
35
+ homepage: https://github.com/BertramScharpf/ruby-qrest.git
36
+ licenses:
37
+ - BSD-2-Clause+
38
+ metadata: {}
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 3.1.0
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubygems_version: 3.6.4
54
+ specification_version: 4
55
+ summary: Generate QR Codes
56
+ test_files: []