diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b5f09..0afa76e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Add a basic benchmark file +- Add standardRB badge +- Add `.freeze` on `CONST` lookup objects +- Remove unused `@mode` instance variable +- A batch of small refactors and optimizations + ## [1.0.0] - 2021-04-23 ### Changed diff --git a/README.md b/README.md index ba328ca..efe1e14 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ ![](https://github.com/whomwah/rqrcode_core/actions/workflows/ruby.yml/badge.svg) +[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard) # RQRCodeCore diff --git a/Rakefile b/Rakefile index ba9e2c1..c71f017 100644 --- a/Rakefile +++ b/Rakefile @@ -9,6 +9,11 @@ begin end task default: [:test, "standard:fix"] + + desc "Run a simple benchmark (x1000)" + task :benchmark do + ruby "test/benchmark.rb" + end rescue LoadError # no standard/rspec available end diff --git a/lib/rqrcode_core/qrcode/qr_8bit_byte.rb b/lib/rqrcode_core/qrcode/qr_8bit_byte.rb index 706b32f..320fb1f 100644 --- a/lib/rqrcode_core/qrcode/qr_8bit_byte.rb +++ b/lib/rqrcode_core/qrcode/qr_8bit_byte.rb @@ -2,19 +2,13 @@ module RQRCodeCore class QR8bitByte - attr_reader :mode - def initialize(data) - @mode = QRMODE[:mode_8bit_byte] @data = data end - def get_length - @data.bytesize - end - def write(buffer) - buffer.byte_encoding_start(get_length) + buffer.byte_encoding_start(@data.bytesize) + @data.each_byte do |b| buffer.put(b, 8) end diff --git a/lib/rqrcode_core/qrcode/qr_alphanumeric.rb b/lib/rqrcode_core/qrcode/qr_alphanumeric.rb index e948a12..c7b97dd 100644 --- a/lib/rqrcode_core/qrcode/qr_alphanumeric.rb +++ b/lib/rqrcode_core/qrcode/qr_alphanumeric.rb @@ -1,32 +1,27 @@ # frozen_string_literal: true module RQRCodeCore - ALPHANUMERIC = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", " ", "$", "%", "*", "+", "-", ".", "/", ":"] + ALPHANUMERIC = [ + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", " ", "$", + "%", "*", "+", "-", ".", "/", ":" + ].freeze class QRAlphanumeric - attr_reader :mode - def initialize(data) - @mode = QRMODE[:mode_alpha_numk] - - raise QRCodeArgumentError, "Not a alpha numeric uppercase string `#{data}`" unless QRAlphanumeric.valid_data?(data) + unless QRAlphanumeric.valid_data?(data) + raise QRCodeArgumentError, "Not a alpha numeric uppercase string `#{data}`" + end @data = data end - def get_length - @data.size - end - - def self.valid_data? data - data.each_char do |s| - return false if ALPHANUMERIC.index(s).nil? - end - true + def self.valid_data?(data) + (data.chars - ALPHANUMERIC).empty? end def write(buffer) - buffer.alphanumeric_encoding_start(get_length) + buffer.alphanumeric_encoding_start(@data.size) @data.size.times do |i| if i % 2 == 0 diff --git a/lib/rqrcode_core/qrcode/qr_bit_buffer.rb b/lib/rqrcode_core/qrcode/qr_bit_buffer.rb index e71fae1..1aa29fc 100644 --- a/lib/rqrcode_core/qrcode/qr_bit_buffer.rb +++ b/lib/rqrcode_core/qrcode/qr_bit_buffer.rb @@ -64,8 +64,8 @@ def pad_until(prefered_size) # Pad with padding code words while get_length_in_bits < prefered_size - put(QRBitBuffer::PAD0, 8) - put(QRBitBuffer::PAD1, 8) if get_length_in_bits < prefered_size + put(PAD0, 8) + put(PAD1, 8) if get_length_in_bits < prefered_size end end diff --git a/lib/rqrcode_core/qrcode/qr_code.rb b/lib/rqrcode_core/qrcode/qr_code.rb index 510e7a3..9777ddb 100644 --- a/lib/rqrcode_core/qrcode/qr_code.rb +++ b/lib/rqrcode_core/qrcode/qr_code.rb @@ -5,20 +5,20 @@ module RQRCodeCore mode_number: 1 << 0, mode_alpha_numk: 1 << 1, mode_8bit_byte: 1 << 2 - } + }.freeze QRMODE_NAME = { number: :mode_number, alphanumeric: :mode_alpha_numk, byte_8bit: :mode_8bit_byte - } + }.freeze QRERRORCORRECTLEVEL = { l: 1, m: 0, q: 3, h: 2 - } + }.freeze QRMASKPATTERN = { pattern000: 0, @@ -29,7 +29,7 @@ module RQRCodeCore pattern101: 5, pattern110: 6, pattern111: 7 - } + }.freeze QRMASKCOMPUTATIONS = [ proc { |i, j| (i + j) % 2 == 0 }, @@ -40,7 +40,7 @@ module RQRCodeCore proc { |i, j| (i * j) % 2 + (i * j) % 3 == 0 }, proc { |i, j| ((i * j) % 2 + (i * j) % 3) % 2 == 0 }, proc { |i, j| ((i * j) % 3 + (i + j) % 2) % 2 == 0 } - ] + ].freeze QRPOSITIONPATTERNLENGTH = (7 + 1) * 2 + 1 QRFORMATINFOLENGTH = 15 @@ -132,7 +132,7 @@ module RQRCodeCore 790, 842, 898, 958, 983, 1051, 1093, 1139, 1219, 1273 ] } - } + }.freeze # StandardErrors @@ -314,7 +314,7 @@ def make #:nodoc: private - def prepare_common_patterns + def prepare_common_patterns #:nodoc: @modules.map! { |row| Array.new(@module_count) } place_position_probe_pattern(0, 0) @@ -490,7 +490,7 @@ def extract_options!(arr) #:nodoc: end class << self - def count_max_data_bits(rs_blocks) + def count_max_data_bits(rs_blocks) #:nodoc: max_data_bytes = rs_blocks.reduce(0) do |sum, rs_block| sum + rs_block.data_count end diff --git a/lib/rqrcode_core/qrcode/qr_math.rb b/lib/rqrcode_core/qrcode/qr_math.rb index 3ff10c9..de24c8b 100644 --- a/lib/rqrcode_core/qrcode/qr_math.rb +++ b/lib/rqrcode_core/qrcode/qr_math.rb @@ -21,8 +21,8 @@ class QRMath log_table[exp_table[i]] = i end - const_set(:EXP_TABLE, exp_table) - const_set(:LOG_TABLE, log_table) + const_set(:EXP_TABLE, exp_table).freeze + const_set(:LOG_TABLE, log_table).freeze } class << self diff --git a/lib/rqrcode_core/qrcode/qr_numeric.rb b/lib/rqrcode_core/qrcode/qr_numeric.rb index ef6d980..83eb460 100644 --- a/lib/rqrcode_core/qrcode/qr_numeric.rb +++ b/lib/rqrcode_core/qrcode/qr_numeric.rb @@ -1,32 +1,21 @@ # frozen_string_literal: true module RQRCodeCore - NUMERIC = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"].freeze + NUMERIC = %w[0 1 2 3 4 5 6 7 8 9].freeze class QRNumeric - attr_reader :mode - def initialize(data) - @mode = QRMODE[:mode_number] - raise QRCodeArgumentError, "Not a numeric string `#{data}`" unless QRNumeric.valid_data?(data) @data = data end - def get_length - @data.size - end - - def self.valid_data? data - data.each_char do |s| - return false if NUMERIC.index(s).nil? - end - true + def self.valid_data?(data) + (data.chars - NUMERIC).empty? end def write(buffer) - buffer.numeric_encoding_start(get_length) + buffer.numeric_encoding_start(@data.size) @data.size.times do |i| if i % 3 == 0 diff --git a/lib/rqrcode_core/qrcode/qr_rs_block.rb b/lib/rqrcode_core/qrcode/qr_rs_block.rb index 8797bae..15d35a5 100644 --- a/lib/rqrcode_core/qrcode/qr_rs_block.rb +++ b/lib/rqrcode_core/qrcode/qr_rs_block.rb @@ -10,7 +10,7 @@ def initialize(total_count, data_count) end # http://www.thonky.com/qr-code-tutorial/error-correction-table/ - RQRCodeCore::QRRSBlock::RS_BLOCK_TABLE = [ + RS_BLOCK_TABLE = [ # L # M # Q @@ -256,7 +256,7 @@ def initialize(total_count, data_count) [34, 54, 24, 34, 55, 25], [20, 45, 15, 61, 46, 16] - ] + ].freeze def self.get_rs_blocks(version, error_correct_level) rs_block = QRRSBlock.get_rs_block_table(version, error_correct_level) diff --git a/lib/rqrcode_core/qrcode/qr_util.rb b/lib/rqrcode_core/qrcode/qr_util.rb index 89e0575..5522da2 100644 --- a/lib/rqrcode_core/qrcode/qr_util.rb +++ b/lib/rqrcode_core/qrcode/qr_util.rb @@ -43,7 +43,7 @@ class QRUtil [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170] - ] + ].freeze G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0 G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0 @@ -59,7 +59,7 @@ class QRUtil QRMODE[:mode_alpha_numk] => [9, 11, 13], QRMODE[:mode_8bit_byte] => [8, 16, 16], QRMODE[:mode_kanji] => [8, 10, 12] - } + }.freeze def self.max_size PATTERN_POSITION_TABLE.count diff --git a/test/benchmark.rb b/test/benchmark.rb new file mode 100644 index 0000000..680ea23 --- /dev/null +++ b/test/benchmark.rb @@ -0,0 +1,11 @@ +$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__) +require "rqrcode_core" +require "benchmark" + +Benchmark.bm do |benchmark| + benchmark.report("RQRCode") do + 1000.times do + RQRCodeCore::QRCode.new("https://kyan.com").to_s + end + end +end diff --git a/test/rqrcode_core/data.rb b/test/rqrcode_core/data.rb index 5417c73..c814431 100644 --- a/test/rqrcode_core/data.rb +++ b/test/rqrcode_core/data.rb @@ -21,5 +21,3 @@ MATRIX_4_Q = [[true, true, true, true, true, true, true, false, false, true, true, true, false, true, true, true, false, true, true, false, false, true, true, false, true, false, true, true, true, true, true, true, true], [true, false, false, false, false, false, true, false, true, false, false, true, false, false, false, true, true, false, true, true, false, false, false, false, false, false, true, false, false, false, false, false, true], [true, false, true, true, true, false, true, false, false, false, true, true, true, false, true, false, false, false, false, true, true, true, false, true, true, false, true, false, true, true, true, false, true], [true, false, true, true, true, false, true, false, true, false, false, false, true, true, true, false, true, false, true, true, true, false, true, true, true, false, true, false, true, true, true, false, true], [true, false, true, true, true, false, true, false, true, false, true, true, false, false, true, true, false, false, false, false, false, false, true, true, false, false, true, false, true, true, true, false, true], [true, false, false, false, false, false, true, false, false, true, true, false, true, true, false, true, false, true, false, true, false, true, false, false, true, false, true, false, false, false, false, false, true], [true, true, true, true, true, true, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, true, true, true, true, true, true], [false, false, false, false, false, false, false, false, true, true, false, true, true, true, true, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false], [false, true, false, true, true, true, true, false, true, false, false, false, true, true, false, false, true, true, false, false, false, false, false, true, true, true, true, false, true, true, false, true, false], [false, false, false, true, true, true, false, false, true, true, false, false, true, false, false, true, false, true, true, true, false, true, false, true, false, false, false, false, true, true, true, false, false], [true, false, false, false, true, false, true, false, true, false, true, false, true, true, true, false, true, false, false, false, false, false, true, true, false, false, true, false, true, false, false, true, true], [false, false, false, true, true, false, false, false, false, true, false, false, true, false, true, false, false, false, true, false, false, true, true, true, false, false, true, false, true, false, true, true, true], [true, true, true, false, false, true, true, true, false, true, true, false, true, false, false, true, true, true, false, true, false, true, false, true, false, false, true, true, false, false, false, false, false], [true, false, false, false, true, false, false, false, true, false, false, true, true, false, false, true, false, false, true, true, true, false, false, false, true, true, false, true, false, false, true, false, false], [true, false, true, false, true, true, true, true, false, false, false, false, true, false, true, false, true, true, true, true, true, true, true, false, false, false, true, true, true, false, false, false, false], [true, false, true, true, false, false, false, false, false, true, true, true, true, false, false, false, true, false, false, false, true, false, true, false, true, false, false, false, true, false, true, true, false], [false, false, true, false, false, false, true, false, true, false, true, false, false, true, true, true, false, true, true, false, true, false, true, true, false, true, true, true, true, false, false, true, true], [true, true, false, false, true, false, false, true, false, true, true, false, false, true, false, true, false, true, false, true, true, false, false, false, false, false, true, true, true, false, true, false, true], [true, false, true, true, true, true, true, true, true, false, false, false, true, true, true, false, true, false, false, true, true, true, true, true, true, false, false, true, false, false, false, true, true], [true, false, false, false, true, true, false, false, true, true, false, true, false, false, false, true, true, true, true, false, true, false, true, true, false, true, true, false, false, false, true, false, false], [true, false, true, true, false, true, true, false, true, false, true, true, false, false, false, true, true, true, false, true, false, true, true, true, true, false, false, false, false, false, false, true, false], [true, false, true, false, true, true, false, false, false, true, false, false, false, true, false, false, true, false, true, false, false, false, false, false, false, true, false, false, true, false, true, true, false], [true, false, false, false, true, false, true, false, true, true, false, true, false, false, false, true, true, false, true, true, true, false, false, false, true, false, true, false, false, true, true, true, true], [true, false, false, false, false, false, false, false, true, false, false, false, false, true, true, false, false, true, true, true, true, false, true, false, false, true, true, false, false, true, true, true, false], [true, true, true, false, false, true, true, false, true, true, false, false, true, true, false, false, false, false, true, false, false, false, false, false, true, true, true, true, true, false, false, true, true], [false, false, false, false, false, false, false, false, true, true, false, false, true, false, true, true, true, false, false, false, false, true, false, false, true, false, false, false, true, true, false, false, false], [true, true, true, true, true, true, true, false, false, true, false, true, true, true, true, true, true, false, true, true, true, false, false, true, true, false, true, false, true, false, false, false, false], [true, false, false, false, false, false, true, false, true, true, false, true, true, true, false, false, true, false, false, true, false, true, true, false, true, false, false, false, true, true, true, true, true], [true, false, true, true, true, false, true, false, true, false, true, true, false, false, false, false, true, false, true, false, false, true, true, true, true, true, true, true, true, true, false, true, true], [true, false, true, true, true, false, true, false, true, true, false, false, true, true, true, false, true, false, true, false, false, true, true, false, false, true, false, false, false, true, true, false, true], [true, false, true, true, true, false, true, false, false, true, true, false, true, true, false, false, true, true, true, true, false, false, false, false, false, true, false, false, true, true, true, true, true], [true, false, false, false, false, false, true, false, true, true, false, false, true, false, false, true, false, true, false, true, true, false, true, false, true, false, true, false, true, false, true, true, true], [true, true, true, true, true, true, true, false, false, true, true, false, true, true, true, false, true, false, true, true, false, false, false, false, true, false, true, true, true, true, false, false, false]] MATRIX_UTF8_RU_TEST = [[true, true, true, true, true, true, true, false, true, false, true, true, true, true, true, false, false, false, true, true, true, true, true, true, true], [true, false, false, false, false, false, true, false, false, false, false, false, true, true, true, true, true, false, true, false, false, false, false, false, true], [true, false, true, true, true, false, true, false, true, false, false, true, false, true, true, true, true, false, true, false, true, true, true, false, true], [true, false, true, true, true, false, true, false, false, false, true, false, true, true, false, true, true, false, true, false, true, true, true, false, true], [true, false, true, true, true, false, true, false, true, false, false, true, true, true, false, true, false, false, true, false, true, true, true, false, true], [true, false, false, false, false, false, true, false, false, true, false, false, true, true, false, true, false, false, true, false, false, false, false, false, true], [true, true, true, true, true, true, true, false, true, false, true, false, true, false, true, false, true, false, true, true, true, true, true, true, true], [false, false, false, false, false, false, false, false, true, true, true, false, false, false, false, true, true, false, false, false, false, false, false, false, false], [false, false, false, false, false, true, true, false, false, false, true, false, true, true, false, true, false, false, true, false, true, false, true, false, true], [false, false, false, false, false, true, false, true, true, true, true, true, false, true, true, true, false, false, true, true, false, false, true, true, true], [false, true, true, false, true, true, true, false, false, false, false, false, false, true, false, false, false, false, true, false, true, true, false, true, false], [true, true, false, false, true, false, false, false, false, false, true, false, false, false, false, true, false, true, true, true, true, false, true, false, false], [false, false, false, false, false, false, true, true, false, false, false, false, true, true, false, false, false, true, true, true, true, false, false, true, true], [true, true, true, true, false, true, false, false, false, true, false, true, false, false, true, false, false, true, true, false, false, true, false, false, true], [true, false, false, true, true, false, true, true, true, false, false, true, true, true, false, true, true, true, false, false, true, false, false, false, false], [true, false, false, false, false, false, false, false, true, true, false, false, false, true, false, false, true, false, false, false, true, true, false, true, true], [true, false, true, true, true, true, true, true, false, false, true, false, false, true, true, true, true, true, true, true, true, false, false, false, true], [false, false, false, false, false, false, false, false, true, false, false, false, false, true, true, false, true, false, false, false, true, false, false, true, true], [true, true, true, true, true, true, true, false, false, true, true, true, false, true, false, true, true, false, true, false, true, false, true, false, false], [true, false, false, false, false, false, true, false, true, true, false, false, true, false, true, true, true, false, false, false, true, false, true, false, true], [true, false, true, true, true, false, true, false, false, true, false, true, true, false, false, false, true, true, true, true, true, true, false, false, false], [true, false, true, true, true, false, true, false, false, true, true, true, true, true, false, false, false, true, false, false, true, false, true, false, true], [true, false, true, true, true, false, true, false, false, true, false, false, false, true, false, false, true, false, true, false, true, false, false, false, true], [true, false, false, false, false, false, true, false, false, true, false, false, false, false, true, true, false, false, true, true, false, true, true, false, true], [true, true, true, true, true, true, true, false, false, true, false, true, false, false, false, true, true, false, true, true, true, false, true, false, true]] - -AS_ANSI = "\e[47m \e[m\n\e[47m \e[m\n\e[47m \e[m\n\e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[40m \e[47m \e[m\n\e[47m \e[m\n\e[47m \e[m\n\e[47m \e[m\n\e[47m \e[m\n" diff --git a/test/rqrcode_core/rqrcode_test.rb b/test/rqrcode_core/rqrcode_test.rb index 5144822..61c54b3 100644 --- a/test/rqrcode_core/rqrcode_test.rb +++ b/test/rqrcode_core/rqrcode_test.rb @@ -81,6 +81,14 @@ def test_auto_alphanumeric assert_equal "xxxxxxx xxx xxxxxxx\n", qr.to_s[0..21] end + def test_manual_alphanumeric + assert_equal :mode_alpha_numk, RQRCodeCore::QRCode.new("DUNCAN", mode: :alphanumeric).mode + + assert_raises(RQRCodeCore::QRCodeArgumentError) { + RQRCodeCore::QRCode.new("Duncan", mode: :alphanumeric) + } + end + def test_auto_numeric # When digit only automatically uses numeric mode, default ecc level is :h digits = RQRCodeCore::QRCode.new("1" * 17) # Version 1, numeric mode, ECC h