rqrcode_core 0.1.2 → 1.2.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.
@@ -6,39 +6,38 @@ module RQRCodeCore
6
6
  exp_table = Array.new(256)
7
7
  log_table = Array.new(256)
8
8
 
9
- ( 0...8 ).each do |i|
9
+ (0...8).each do |i|
10
10
  exp_table[i] = 1 << i
11
11
  end
12
12
 
13
- ( 8...256 ).each do |i|
13
+ (8...256).each do |i|
14
14
  exp_table[i] = exp_table[i - 4] \
15
15
  ^ exp_table[i - 5] \
16
16
  ^ exp_table[i - 6] \
17
17
  ^ exp_table[i - 8]
18
18
  end
19
19
 
20
- ( 0...255 ).each do |i|
21
- log_table[exp_table[i] ] = i
20
+ (0...255).each do |i|
21
+ log_table[exp_table[i]] = i
22
22
  end
23
23
 
24
- EXP_TABLE = exp_table
25
- LOG_TABLE = log_table
24
+ const_set(:EXP_TABLE, exp_table).freeze
25
+ const_set(:LOG_TABLE, log_table).freeze
26
26
  }
27
27
 
28
28
  class << self
29
29
  def glog(n)
30
- raise QRCodeRunTimeError, "glog(#{n})" if ( n < 1 )
30
+ raise QRCodeRunTimeError, "glog(#{n})" if n < 1
31
31
  LOG_TABLE[n]
32
32
  end
33
33
 
34
-
35
34
  def gexp(n)
36
35
  while n < 0
37
- n = n + 255
36
+ n += 255
38
37
  end
39
38
 
40
39
  while n >= 256
41
- n = n - 255
40
+ n -= 255
42
41
  end
43
42
 
44
43
  EXP_TABLE[n]
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RQRCodeCore
4
+ class QRMulti
5
+ def initialize(data)
6
+ @data = data
7
+ end
8
+
9
+ def write(buffer)
10
+ @data.each { |seg| seg.writer.write(buffer) }
11
+ end
12
+ end
13
+ end
@@ -1,38 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RQRCodeCore
4
- NUMERIC = ['0','1','2','3','4','5','6','7','8','9'].freeze
4
+ NUMERIC = %w[0 1 2 3 4 5 6 7 8 9].freeze
5
5
 
6
6
  class QRNumeric
7
- attr_reader :mode
8
-
9
- def initialize( data )
10
- @mode = QRMODE[:mode_number]
11
-
7
+ def initialize(data)
12
8
  raise QRCodeArgumentError, "Not a numeric string `#{data}`" unless QRNumeric.valid_data?(data)
13
9
 
14
- @data = data;
10
+ @data = data
15
11
  end
16
12
 
17
- def get_length
18
- @data.size
19
- end
20
-
21
- def self.valid_data? data
22
- data.each_char do |s|
23
- return false if NUMERIC.index(s).nil?
24
- end
25
- true
13
+ def self.valid_data?(data)
14
+ (data.chars - NUMERIC).empty?
26
15
  end
27
16
 
28
- def write( buffer)
29
- buffer.numeric_encoding_start(get_length)
17
+ def write(buffer)
18
+ buffer.numeric_encoding_start(@data.size)
30
19
 
31
- (@data.size).times do |i|
20
+ @data.size.times do |i|
32
21
  if i % 3 == 0
33
22
  chars = @data[i, 3]
34
23
  bit_length = get_bit_length(chars.length)
35
- buffer.put( get_code(chars), bit_length )
24
+ buffer.put(get_code(chars), bit_length)
36
25
  end
37
26
  end
38
27
  end
@@ -2,22 +2,22 @@
2
2
 
3
3
  module RQRCodeCore
4
4
  class QRPolynomial
5
- def initialize( num, shift )
5
+ def initialize(num, shift)
6
6
  raise QRCodeRunTimeError, "#{num.size}/#{shift}" if num.empty?
7
7
  offset = 0
8
8
 
9
9
  while offset < num.size && num[offset] == 0
10
- offset = offset + 1
10
+ offset += 1
11
11
  end
12
12
 
13
- @num = Array.new( num.size - offset + shift )
13
+ @num = Array.new(num.size - offset + shift)
14
14
 
15
- ( 0...num.size - offset ).each do |i|
15
+ (0...num.size - offset).each do |i|
16
16
  @num[i] = num[i + offset]
17
17
  end
18
18
  end
19
19
 
20
- def get( index )
20
+ def get(index)
21
21
  @num[index]
22
22
  end
23
23
 
@@ -25,20 +25,20 @@ module RQRCodeCore
25
25
  @num.size
26
26
  end
27
27
 
28
- def multiply( e )
29
- num = Array.new( get_length + e.get_length - 1 )
28
+ def multiply(e)
29
+ num = Array.new(get_length + e.get_length - 1)
30
30
 
31
- ( 0...get_length ).each do |i|
32
- ( 0...e.get_length ).each do |j|
31
+ (0...get_length).each do |i|
32
+ (0...e.get_length).each do |j|
33
33
  tmp = num[i + j].nil? ? 0 : num[i + j]
34
- num[i + j] = tmp ^ QRMath.gexp(QRMath.glog( get(i) ) + QRMath.glog(e.get(j)))
34
+ num[i + j] = tmp ^ QRMath.gexp(QRMath.glog(get(i)) + QRMath.glog(e.get(j)))
35
35
  end
36
36
  end
37
37
 
38
- return QRPolynomial.new( num, 0 )
38
+ QRPolynomial.new(num, 0)
39
39
  end
40
40
 
41
- def mod( e )
41
+ def mod(e)
42
42
  if get_length - e.get_length < 0
43
43
  return self
44
44
  end
@@ -46,16 +46,16 @@ module RQRCodeCore
46
46
  ratio = QRMath.glog(get(0)) - QRMath.glog(e.get(0))
47
47
  num = Array.new(get_length)
48
48
 
49
- ( 0...get_length ).each do |i|
49
+ (0...get_length).each do |i|
50
50
  num[i] = get(i)
51
51
  end
52
52
 
53
- ( 0...e.get_length ).each do |i|
53
+ (0...e.get_length).each do |i|
54
54
  tmp = num[i].nil? ? 0 : num[i]
55
55
  num[i] = tmp ^ QRMath.gexp(QRMath.glog(e.get(i)) + ratio)
56
56
  end
57
57
 
58
- return QRPolynomial.new( num, 0 ).mod(e)
58
+ QRPolynomial.new(num, 0).mod(e)
59
59
  end
60
60
  end
61
61
  end
@@ -4,13 +4,13 @@ module RQRCodeCore
4
4
  class QRRSBlock
5
5
  attr_reader :data_count, :total_count
6
6
 
7
- def initialize( total_count, data_count )
7
+ def initialize(total_count, data_count)
8
8
  @total_count = total_count
9
9
  @data_count = data_count
10
10
  end
11
11
 
12
12
  # http://www.thonky.com/qr-code-tutorial/error-correction-table/
13
- RQRCodeCore::QRRSBlock::RS_BLOCK_TABLE = [
13
+ RS_BLOCK_TABLE = [
14
14
  # L
15
15
  # M
16
16
  # Q
@@ -256,9 +256,9 @@ module RQRCodeCore
256
256
  [34, 54, 24, 34, 55, 25],
257
257
  [20, 45, 15, 61, 46, 16]
258
258
 
259
- ]
259
+ ].freeze
260
260
 
261
- def QRRSBlock.get_rs_blocks(version, error_correct_level)
261
+ def self.get_rs_blocks(version, error_correct_level)
262
262
  rs_block = QRRSBlock.get_rs_block_table(version, error_correct_level)
263
263
 
264
264
  if rs_block.nil?
@@ -269,20 +269,20 @@ module RQRCodeCore
269
269
  length = rs_block.size / 3
270
270
  list = []
271
271
 
272
- ( 0...length ).each do |i|
272
+ (0...length).each do |i|
273
273
  count = rs_block[i * 3 + 0]
274
274
  total_count = rs_block[i * 3 + 1]
275
275
  data_count = rs_block[i * 3 + 2]
276
276
 
277
- ( 0...count ).each do |j|
278
- list << QRRSBlock.new( total_count, data_count )
277
+ (0...count).each do |j|
278
+ list << QRRSBlock.new(total_count, data_count)
279
279
  end
280
280
  end
281
281
 
282
282
  list
283
283
  end
284
284
 
285
- def QRRSBlock.get_rs_block_table(version, error_correct_level)
285
+ def self.get_rs_block_table(version, error_correct_level)
286
286
  case error_correct_level
287
287
  when QRERRORCORRECTLEVEL[:l]
288
288
  QRRSBlock::RS_BLOCK_TABLE[(version - 1) * 4 + 0]
@@ -292,8 +292,6 @@ module RQRCodeCore
292
292
  QRRSBlock::RS_BLOCK_TABLE[(version - 1) * 4 + 2]
293
293
  when QRERRORCORRECTLEVEL[:h]
294
294
  QRRSBlock::RS_BLOCK_TABLE[(version - 1) * 4 + 3]
295
- else
296
- nil
297
295
  end
298
296
  end
299
297
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RQRCodeCore
4
+ class QRSegment
5
+ attr_reader :data, :mode
6
+
7
+ def initialize(data:, mode: nil)
8
+ @data = data
9
+ @mode = QRMODE_NAME.dig(mode&.to_sym)
10
+
11
+ # If mode is not explicitely found choose mode according to data type
12
+ @mode ||= if RQRCodeCore::QRNumeric.valid_data?(@data)
13
+ QRMODE_NAME[:number]
14
+ elsif QRAlphanumeric.valid_data?(@data)
15
+ QRMODE_NAME[:alphanumeric]
16
+ else
17
+ QRMODE_NAME[:byte_8bit]
18
+ end
19
+ end
20
+
21
+ def size(version)
22
+ 4 + header_size(version) + content_size
23
+ end
24
+
25
+ def header_size(version)
26
+ QRUtil.get_length_in_bits(QRMODE[mode], version)
27
+ end
28
+
29
+ def content_size
30
+ chunk_size, bit_length, extra = case mode
31
+ when :mode_number
32
+ [3, QRNumeric::NUMBER_LENGTH[3], QRNumeric::NUMBER_LENGTH[data_length % 3] || 0]
33
+ when :mode_alpha_numk
34
+ [2, 11, 6]
35
+ when :mode_8bit_byte
36
+ [1, 8, 0]
37
+ end
38
+
39
+ (data_length / chunk_size) * bit_length + ((data_length % chunk_size) == 0 ? 0 : extra)
40
+ end
41
+
42
+ def writer
43
+ case mode
44
+ when :mode_number
45
+ QRNumeric.new(data)
46
+ when :mode_alpha_numk
47
+ QRAlphanumeric.new(data)
48
+ when :mode_multi
49
+ QRMulti.new(data)
50
+ else
51
+ QR8bitByte.new(data)
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def data_length
58
+ data.bytesize
59
+ end
60
+ end
61
+ end
@@ -43,7 +43,7 @@ module RQRCodeCore
43
43
  [6, 32, 58, 84, 110, 136, 162],
44
44
  [6, 26, 54, 82, 110, 138, 166],
45
45
  [6, 30, 58, 86, 114, 142, 170]
46
- ]
46
+ ].freeze
47
47
 
48
48
  G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0
49
49
  G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0
@@ -58,70 +58,70 @@ module RQRCodeCore
58
58
  QRMODE[:mode_number] => [10, 12, 14],
59
59
  QRMODE[:mode_alpha_numk] => [9, 11, 13],
60
60
  QRMODE[:mode_8bit_byte] => [8, 16, 16],
61
- QRMODE[:mode_kanji] => [8, 10, 12],
62
- }
61
+ QRMODE[:mode_kanji] => [8, 10, 12]
62
+ }.freeze
63
63
 
64
- def QRUtil.max_size
64
+ def self.max_size
65
65
  PATTERN_POSITION_TABLE.count
66
66
  end
67
67
 
68
- def QRUtil.get_bch_format_info( data )
68
+ def self.get_bch_format_info(data)
69
69
  d = data << 10
70
70
  while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15) >= 0
71
71
  d ^= (G15 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15)))
72
72
  end
73
- (( data << 10 ) | d) ^ G15_MASK
73
+ ((data << 10) | d) ^ G15_MASK
74
74
  end
75
75
 
76
- def QRUtil.rszf( num, count )
76
+ def self.rszf(num, count)
77
77
  # zero fill right shift
78
- (num >> count) & ((2 ** ((num.size * 8) - count))-1)
78
+ (num >> count) & ((2**((num.size * 8) - count)) - 1)
79
79
  end
80
80
 
81
- def QRUtil.get_bch_version(data)
81
+ def self.get_bch_version(data)
82
82
  d = data << 12
83
83
  while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G18) >= 0
84
84
  d ^= (G18 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G18)))
85
85
  end
86
- ( data << 12 ) | d
86
+ (data << 12) | d
87
87
  end
88
88
 
89
- def QRUtil.get_bch_digit( data )
89
+ def self.get_bch_digit(data)
90
90
  digit = 0
91
91
 
92
92
  while data != 0
93
- digit = digit + 1
94
- data = QRUtil.rszf( data, 1 )
93
+ digit += 1
94
+ data = QRUtil.rszf(data, 1)
95
95
  end
96
96
 
97
97
  digit
98
98
  end
99
99
 
100
- def QRUtil.get_pattern_positions(version)
100
+ def self.get_pattern_positions(version)
101
101
  PATTERN_POSITION_TABLE[version - 1]
102
102
  end
103
103
 
104
- def QRUtil.get_mask( mask_pattern, i, j )
104
+ def self.get_mask(mask_pattern, i, j)
105
105
  if mask_pattern > QRMASKCOMPUTATIONS.size
106
106
  raise QRCodeRunTimeError, "bad mask_pattern: #{mask_pattern}"
107
107
  end
108
108
 
109
- return QRMASKCOMPUTATIONS[mask_pattern].call(i, j)
109
+ QRMASKCOMPUTATIONS[mask_pattern].call(i, j)
110
110
  end
111
111
 
112
- def QRUtil.get_error_correct_polynomial( error_correct_length )
113
- a = QRPolynomial.new( [1], 0 )
112
+ def self.get_error_correct_polynomial(error_correct_length)
113
+ a = QRPolynomial.new([1], 0)
114
114
 
115
- ( 0...error_correct_length ).each do |i|
116
- a = a.multiply( QRPolynomial.new( [1, QRMath.gexp(i)], 0 ) )
115
+ (0...error_correct_length).each do |i|
116
+ a = a.multiply(QRPolynomial.new([1, QRMath.gexp(i)], 0))
117
117
  end
118
118
 
119
119
  a
120
120
  end
121
121
 
122
- def QRUtil.get_length_in_bits(mode, version)
122
+ def self.get_length_in_bits(mode, version)
123
123
  if !QRMODE.value?(mode)
124
- raise QRCodeRunTimeError, "Unknown mode: #{mode}"
124
+ raise QRCodeRunTimeError, "Unknown mode: #{mode}"
125
125
  end
126
126
 
127
127
  if version > 40
@@ -139,10 +139,10 @@ module RQRCodeCore
139
139
  macro_version = 2
140
140
  end
141
141
 
142
- return BITS_FOR_MODE[mode][macro_version]
142
+ BITS_FOR_MODE[mode][macro_version]
143
143
  end
144
144
 
145
- def QRUtil.get_lost_points(modules)
145
+ def self.get_lost_points(modules)
146
146
  demerit_points = 0
147
147
 
148
148
  demerit_points += QRUtil.demerit_points_1_same_color(modules)
@@ -150,10 +150,10 @@ module RQRCodeCore
150
150
  demerit_points += QRUtil.demerit_points_3_dangerous_patterns(modules)
151
151
  demerit_points += QRUtil.demerit_points_4_dark_ratio(modules)
152
152
 
153
- return demerit_points
153
+ demerit_points
154
154
  end
155
155
 
156
- def QRUtil.demerit_points_1_same_color(modules)
156
+ def self.demerit_points_1_same_color(modules)
157
157
  demerit_points = 0
158
158
  module_count = modules.size
159
159
 
@@ -163,10 +163,10 @@ module RQRCodeCore
163
163
  same_count = 0
164
164
  dark = modules[row][col]
165
165
 
166
- ( -1..1 ).each do |r|
166
+ (-1..1).each do |r|
167
167
  next if row + r < 0 || module_count <= row + r
168
168
 
169
- ( -1..1 ).each do |c|
169
+ (-1..1).each do |c|
170
170
  next if col + c < 0 || module_count <= col + c
171
171
  next if r == 0 && c == 0
172
172
  if dark == modules[row + r][col + c]
@@ -181,10 +181,10 @@ module RQRCodeCore
181
181
  end
182
182
  end
183
183
 
184
- return demerit_points
184
+ demerit_points
185
185
  end
186
186
 
187
- def QRUtil.demerit_points_2_full_blocks(modules)
187
+ def self.demerit_points_2_full_blocks(modules)
188
188
  demerit_points = 0
189
189
  module_count = modules.size
190
190
 
@@ -196,16 +196,16 @@ module RQRCodeCore
196
196
  count += 1 if modules[row + 1][col]
197
197
  count += 1 if modules[row][col + 1]
198
198
  count += 1 if modules[row + 1][col + 1]
199
- if (count == 0 || count == 4)
199
+ if count == 0 || count == 4
200
200
  demerit_points += DEMERIT_POINTS_2
201
201
  end
202
202
  end
203
203
  end
204
204
 
205
- return demerit_points
205
+ demerit_points
206
206
  end
207
207
 
208
- def QRUtil.demerit_points_3_dangerous_patterns(modules)
208
+ def self.demerit_points_3_dangerous_patterns(modules)
209
209
  demerit_points = 0
210
210
  module_count = modules.size
211
211
 
@@ -213,12 +213,12 @@ module RQRCodeCore
213
213
  modules.each do |row|
214
214
  (module_count - 6).times do |col_idx|
215
215
  if row[col_idx] &&
216
- !row[col_idx + 1] &&
217
- row[col_idx + 2] &&
218
- row[col_idx + 3] &&
219
- row[col_idx + 4] &&
220
- !row[col_idx + 5] &&
221
- row[col_idx + 6]
216
+ !row[col_idx + 1] &&
217
+ row[col_idx + 2] &&
218
+ row[col_idx + 3] &&
219
+ row[col_idx + 4] &&
220
+ !row[col_idx + 5] &&
221
+ row[col_idx + 6]
222
222
  demerit_points += DEMERIT_POINTS_3
223
223
  end
224
224
  end
@@ -227,21 +227,21 @@ module RQRCodeCore
227
227
  (0...module_count).each do |col|
228
228
  (0...(module_count - 6)).each do |row|
229
229
  if modules[row][col] &&
230
- !modules[row + 1][col] &&
231
- modules[row + 2][col] &&
232
- modules[row + 3][col] &&
233
- modules[row + 4][col] &&
234
- !modules[row + 5][col] &&
235
- modules[row + 6][col]
230
+ !modules[row + 1][col] &&
231
+ modules[row + 2][col] &&
232
+ modules[row + 3][col] &&
233
+ modules[row + 4][col] &&
234
+ !modules[row + 5][col] &&
235
+ modules[row + 6][col]
236
236
  demerit_points += DEMERIT_POINTS_3
237
237
  end
238
238
  end
239
239
  end
240
240
 
241
- return demerit_points
241
+ demerit_points
242
242
  end
243
243
 
244
- def QRUtil.demerit_points_4_dark_ratio(modules)
244
+ def self.demerit_points_4_dark_ratio(modules)
245
245
  # level 4
246
246
  dark_count = modules.reduce(0) do |sum, col|
247
247
  sum + col.count(true)
@@ -250,8 +250,7 @@ module RQRCodeCore
250
250
  ratio = dark_count / (modules.size * modules.size)
251
251
  ratio_delta = (100 * ratio - 50).abs / 5
252
252
 
253
- demerit_points = ratio_delta * DEMERIT_POINTS_4
254
- return demerit_points
253
+ ratio_delta * DEMERIT_POINTS_4
255
254
  end
256
255
  end
257
256
  end